一个包能绑十个发布身份,你却还在 CI 里揣着一根永不过期的 token——npm 9 月 3 日把信任发布的规则改了

一个包现在能绑定十个”发布身份”,可你的 CI 里可能还躺着一根永不过期的 publish token——npm 在 9 月 3 日把「信任发布」的规则改了,而且改法有个反直觉的坑:配置是累加的,你新加的那条更窄的规则,管不住旧的那条更宽的规则。

先说结论:这次三个变更里,真正会咬人的不是”多了几个配置”,而是”新规则不会自动收窄旧规则”。你的安全边界等于所有配置的并集,不是最后写的那条。

9 月 3 日到底改了什么

GitHub Changelog 当天发了一条 npm trusted publishing 的 GA 更新,三件事一起上:

  • 一个包可以配多个 trusted publisher,不再只有一个(npm 文档现在允许最多十个)
  • staged(暂存)版本在 npm 的发布时恶意软件扫描跑完之前,不允许被批准
  • 维护者可以在包版本界面里查看 staged / approved / rejected 的完整历史

听起来都是”更安全了”,对吧。问题出在第一条的语义上。

坑在哪:配错了——授权是并集,不是交集

官方描述得很清楚:多个配置之间是独立且累加的,任何一个 incoming OIDC identity 只要匹配上任意一条被允许的配置,就能执行对应动作;而且匹配顺序不保证。

翻译成人话:

# 你两年前配的:任何 main 分支的 push 都能直接 publish
publisher: repo=team/app, workflow=publish.yml, action=publish

# 你这次新加的:只允许 release 环境 + 签名 tag 的步骤发布
publisher: repo=team/app, workflow=hotfix.yml, environment=release, action=stage

你以为第二行收紧了口子。实际上第一行还在,攻击者(或者一个忘了删的旧 workflow、一个改过名的文件、一张留作”应急”的长期 token、一条自托管 runner 的路径)照样能走第一行直接发布。

这就是把”多配置”当成便利功能、而不是当成发布治理问题来对待的代价。

正确的用法:stage-only + 硬件 2FA 人工批准

Evil Martians 团队给的路子比较稳,核心是把 CI 和”最终发布权”拆开:

  1. CI 里跑 npm stage publish,而不是 npm publish
  2. 配置 trusted publishing,只允许 stage 这个 action,把直接 publish 关掉
  3. 打开 npm 用户菜单里的 Staged Packages,或者用 npm stage approve,用硬件 2FA 手动批准

这样即使 CI 被拿下,攻击者也发布不出去,只能干等你自己发布。npm 现在还会在恶意软件扫描跑完之前锁住批准按钮,多了一道闸。

别忘了 provenance 不是免罪金牌

npm Provenance 回答的是”这个包是不是来自正确的流水线”,它不回答”这条流水线当时是不是干净的”。

2026 年 8 月有一波 npm 供应链蠕虫(payload 是个 5.4MB 的 JS 文件,用 XOR + AES-GCM 加密、下载 Bun runtime 偷凭证),攻击者利用的正是发布用的 GitHub Actions workflow 漏洞——生成的恶意 release 依然带着有效 provenance 签名。所以 provenance 可以看,但不能当信任证明。

今天就能落地的四步

  • 检查你所有包的 trusted publisher 配置,逐条看它的 repo / workflow / environment / action,按并集理解你的真实权限
  • 删掉所有失效配置,把 direct publish 关掉,只留 stage
  • 给 workflow 加上 CI linter——CodeQL 或 zizmor(zizmor 是 Rust 写的,规则更多),避免 pull_request_target 这类 pwn request
  • 把 CI 里的 action 版本从 @v7 这种 tag 换成 commit SHA,因为 tag 不是不可变的,攻击者可以回头改你的 tag

最后一条最容易被忽略:修完 workflow 漏洞后,记得删掉旧分支。有团队修了主分支的 pull_request_target,却留着带旧 workflow 的历史分支——攻击者直接对着旧分支开 PR 就绕过去了。

一句话:多配置是能力,但也意味着你的信任边界需要审计,不是”配了就完事”。

评论区

0 条评论

登录后可评论。

阿监·前端工程化 639 阅读