Skip to content

fix(desktop): 内置 npm 打包排除 lib/commands/test.js,修复 nightly 审计拦截 - #271

Open
Ewan-yuan wants to merge 1 commit into
devfrom
fix/nightly-npm-audit-test-file
Open

Ewan-yuan wants to merge 1 commit into
devfrom
fix/nightly-npm-audit-test-file

Conversation

@Ewan-yuan

Copy link
Copy Markdown
Collaborator

背景

desktop-v0.1.9-nightly.20260924.71 两个平台的 "Audit package contents" 步骤同时失败:

✗ Forbidden loose file: npm/lib/commands/test.js

上个成功版本 .70 不含内置 npm,是 be99fdb1(本机 Agent 适配器一键安装)首次把 npm@11 经 extraResources 打进包后触发的第一次发版。

根因

  • be99fdb1 在 extraResources 里整包拷贝 node_modules/npm → resources/npm,filter 裁掉了 *.md/docs/man/node_modules/.bin,但 npm 自带的 lib/commands/test.js(npm test 子命令的实现文件,运行时只用到 npm install,永远不需要它)留在包里。
  • 发版审计(verify-windows-package.mjs + release-desktop.yml macOS 步骤)的禁出规则 (test|spec)\.[^/]+$ 命中该文件,两平台同时被拦,publish 被 skip。

修复(1 行)

npm extraResources filter 追加 !lib/commands/test.js。已用仓库锁定版本的 app-builder-lib 26.15.3 的 copyDir+FileMatcher 本地探针验证:该 filter 组合下 lib/commands/test.js 被排除,bin/npm-cli.js、其余 commands 均正常拷入;.71 审计仅报这一个文件,排除后即恢复与 .70 等价的绿色状态。

发现但未改(建议另开 issue/PR)

  1. electron-builder extraResources 会静默丢弃 from 目录下的直接 node_modules 子目录(app-builder-lib out/util/filter.js 的 relative === "node_modules" 硬编码)。因此打进包里的 npm 不含其捆绑依赖(@npmcli/config、archy 等 ~70 个包),打包产物里 npm install 会在模块解析处失败——一键安装功能在 packaged 环境实际不可用,dev 环境因走 workspace node_modules 而无感。!node_modules/.bin/** 这行 filter 实际是死代码。
  2. 同样的机制使 resources/open-connector 也一直没有 node_modules(已用 .70 发布产物与本机安装的 .69 验证),而其 server 入口 import 了 @hono/node-server/hono——packaged 环境连接器子进程起来即会 MODULE_NOT_FOUND。此问题自 8 月起一直存在,非本次引入。
  3. 若要让内置 npm 真正可用,可选路线:改走 asar files+asarUnpack(复用 electron-builder 的 node_modules 依赖收集),或加 afterPack 钩子自行拷贝。需要单独评估与打包验证,不混入本次止血修复。

测试

  • 本地探针:目标 filter 在 app-builder-lib 26.15.3 的真实 copyDir 下行为符合预期
  • package.json JSON 合法性
  • 合并后由当晚 scheduled-desktop-release 实际发版验证(CI 全绿 + audit 通过)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

审查结论:无阻塞问题

单行 filter 追加,定位准确、证据链完整,可作为发版止血合入。以下为逐项核验。

核验要点

  1. 审计规则与目标文件吻合。apps/desktop/scripts/verify-windows-package.mjs:42 与 .github/workflows/release-desktop.yml:197 的禁出正则均含 (test|spec)\.[^/]+$ 分支,命中 npm/lib/commands/test.js。两处审计都是先收集全部违规再统一输出(Windows 脚本 accumulate 后打印;macOS 步骤 grep 全量打印),.71 双平台各只报这一个文件,说明拷入的 npm 树里没有第二个禁出文件,排除该文件即可恢复与 .70 等价的绿色。

  2. filter 语义与版本一致性。!lib/commands/test.js 与既有 !docs/**、!man/** 同为相对 from(node_modules/npm)根的 pattern,精确匹配单文件;CI 各处均为 pnpm install --frozen-lockfile,锁定的 app-builder-lib@26.15.3、npm@11.19.1 与 PR 描述的本地探针环境一致,npm 版本不会漂移引入新的禁出文件。

  3. 运行时无回归。内置 npm 的唯一调用点是 apps/desktop/src/main/local-agents/adapter-install.ts:64-72,只 spawn npm-cli.js install --prefix ...,从不执行 npm test。npm 7+ 的 commands 实现是 exec 时按需 require(加载失败回落到 help),缺 lib/commands/test.js 不影响 install 路径;入口 resources/npm/bin/npm-cli.js(local-agent-paths.ts:17)在 filter 下正常保留。

  4. 失败模式安全(fail-closed)。若该排除规则在真实打包环境未按预期生效,下一次 nightly 的 "Audit package contents" 会以同样的 Forbidden loose file: npm/lib/commands/test.js 再次失败,publish 继续 skip——不会静默把违规文件发出去。

非阻塞备注

  1. 本 PR 只恢复审计绿色,一键安装功能在 packaged 环境仍不可用(PR 描述"发现但未改"第 1 条已如实披露):electron-builder extraResources 会丢弃 from 下的直接 node_modules 子目录,打进包里的 npm 缺 @npmcli/config 等约 70 个捆绑依赖,npm install 会在模块解析处失败。该问题源自 be99fdb1,先于本 PR,不是本次引入;但建议尽快另开 issue/PR 跟进(asar files+asarUnpack 或 afterPack 钩子),否则正式版用户首次使用一键安装就会失败。resources/open-connector 的同类问题(第 2 条)同样建议排期。
  2. !node_modules/.bin/** 在上述机制下是死代码,后续重构 filter 时可一并清理,本次不必动。

此 PR 修改了高风险文件,需要人工批准,不会自动合并。

  • apps/desktop/package.json

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant