1实现原理 · 为什么它能做到
解包不靠自研实现,而是运行时用 npx 即时拉取第三方包 @electron/asar 来 extract;参数以数组形式交给 spawn,没有 shell 字符串拼接。
const args = ["-y", "@electron/asar", "extract", asarPath, dest];
还原原始源码树的前提是 .js.map 内嵌 sourcesContent;不满足就退回 prettier 格式化压缩代码——这就是宣称的『decompile』实际能力边界。
only works when the `.js.map` embeds `sourcesContent`
无可用 source map 的 JS/CSS 由 npx prettier --write 批量就地格式化,使压缩代码可读。
const args = ["-y", "prettier", "--write", ...batch];
跨平台应用发现:macOS 枚举 /Applications 与 ~/Applications,Windows 走 LOCALAPPDATA/PROGRAMFILES 等根目录;多命中即报错退出,要求用户改用绝对路径。
const roots = ["/Applications", join(homedir(), "Applications")];
写盘有硬护栏:禁止把输出写给根目录、用户 home 本身或当前工作目录;已存在的非空输出目录必须 --force 才写。
const forbidden = [root, home, cwd];
node_modules 与 webpack/runtime 噪声在解包统计、source-map 还原、prettier 格式化三个环节全部跳过。
return s.includes("node_modules/") || s.startsWith("webpack/runtime/");
source-map 的 sources[] 决定写盘路径,实现上先按 map 所在目录解析、再把可读路径收拢到 restored/ 下,只有无法归约成安全路径时才 hash 兜底。
Use `restored/__unknown/<hash>.<ext>` only when the source name is empty or cannot be reduced to a safe file path.
产物是文件树 + 机器可读报告:默认 ~/Downloads/<AppName>-electron-extract/,含 extract-report.json(计数、warnings),并支持 --json 单行摘要。
join(outputDir, "extract-report.json"),
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | npx(Node 自带)/ bun |
| package | @electron/asar(运行时 npx 拉取,未锁版本) |
| package | prettier(运行时 npx 拉取,未锁版本) |
| cli | bun(首选运行时;无 bun 时由 npx -y bun 兜底) |
4风险提醒 风险提醒:黄色 · 留意使用
- 供应链:运行时拉取未锁版本的第三方包 — 本目录无 package.json/lockfile,@electron/asar 与 prettier 由 `npx -y` 在运行时按 npm 最新版拉取并执行;上游发版或被投毒都会直接影响本地执行结果。介意者建议改为显式安装固定版本后调用。
- 解析不可信输入:被解包的 app 代码与 source map — app.asar 内容来自第三方应用,source map 的 sources[] 直接参与写盘路径构造(以『收拢到 restored/ 下』约束,靠路径消毒而非沙箱);Prettier 解析被处理文件时若解析器有漏洞,属本地文件内容触发的解析面。
- 输出目录语义可能误导 — restored/ 是构建产物中自带的源码副本,不等于与该 app 版本严格对应的官方源码(可能缺少被 tree-shake 的部分、含构建期注入);用于安全审计时不应把 restored/ 当权威依据。
- 平台限制与多命中失败 — Linux 不支持自动发现,必须显式 --asar;同名应用多命中时脚本直接非零退出,agent 需要向用户确认后再跑一次。
5第二遍独立确认
- [ok] 解包委托 @electron/asar(非自研) — main.ts:404 逐字为 `const args = ["-y", "@electron/asar", "extract", asarPath, dest];`,spawn 以 argv 数组调用,无 shell 拼接。
- [ok] npx 拉取未锁版本第三方包(供应链面) — 本目录无 package.json / lockfile,main.ts 内两处 npx 调用分别拉 @electron/asar 与 prettier;SKILL.md Notes 自述 'resolved on-the-fly via `npx -y`',与代码一致。
- [ok] source map 还原能力边界(需内嵌 sourcesContent) — SKILL.md 明写只在 `.js.map` 内嵌 sourcesContent 时可用,未内嵌则跳过并记 warnings;无夸大表述。
- [ok] 写盘护栏(/、home、cwd 拒绝;非空目录需 --force) — main.ts assertSafeOutputDir 用 `const forbidden = [root, home, cwd];`;SKILL.md Safety 段文字与代码一致。
- [ok] 平台支持范围(仅 macOS/Windows 自动发现) — main.ts:310-313 对非 darwin/win32 平台直接抛错要求 --asar;SKILL.md 同述,无夸大。
- [ok] 外部依赖清单是否完整 — 全目录扫描 URL/API/凭证 token 零命中;唯二第三方包为 @electron/asar 与 prettier(均经 npx),运行时 bun/npx 为宿主运行时而非依赖。
- [ok] 元数据(license/stars/commit) — git rev-parse HEAD=1567581c26ec29f4216c6e6835415bf30343b0e3;仓库根 LICENSE 首行 'MIT License'、'Copyright (c) 2026 Jim Liu';GitHub API 返回 MIT / 25926 stars / 2026-09-10T15:13:43Z。
- [discrepancy] 『decompile』措辞与实际能力是否相符 — 出题/触发词里的『decompile Electron』并不等于反编译:实际是解包 + 用构建产物自带的 source map 还原 + Prettier 美化(SKILL.md 自己写明前提是 sourcesContent 存在)。判级与结论不受影响,但详情页应写清这不是字节码/压缩代码的结构化反编译。
6结论
3d2a2257d7155c7c…1567581c26