npm 的“仅暂存”令牌:为还没迁到信任发布的团队留的过渡路

先说结论

  • 官方数据:GitHub 于 2026-09-18 在 Changelog 宣布 npm 细粒度访问令牌新增 Read and write (stage only) 权限。该令牌允许自动化工作流暂存包版本供人工审核,但不能直接向 npm registry 发布新版本。
  • 官方数据:即使用户在令牌上配置了绕过 2FA 用于自动化,npm 仍会拒绝该令牌发起的直接 npm publish 请求。
  • 官方数据:npm 的目标是 2027 年 1 月移除通过 bypass-2FA 令牌直接发布的能力。如果团队还无法迁移到 trusted publishing,stage-only token 是官方给出的迁移路径。
  • 官方数据:使用 staged publishing 需要满足:对目标包有 publish 权限、npm 账号启用 2FA、npm CLI 11.15.0+、Node.js 22.14.0+。
  • 自己判断:这个功能不是终极方案,而是降低短期迁移压力的过渡手段。CI 发布链路团队应把它当作 2027-01 之前的缓冲,而不是长期目标。

证据与过程

为什么会出现 stage-only token

npm 长期允许创建可绕过 2FA 的细粒度访问令牌,方便 CI/CD 直接发布包。但这种令牌一旦泄露,攻击者就能绕过人工确认直接向 registry 推送恶意版本,供应链风险很高。2026 年 7 月底,官方已经 retire 了“限制 bypass-2FA 细粒度令牌”的相关功能,并明确后续会进一步收紧。到 2026-09-18,stage-only token 作为新的选项出现:保留自动化的“暂存”能力,但把最终发布权交还给启用 2FA 的人类维护者。

这背后的逻辑很清晰:CI 可以继续做构建、测试、打包、暂存,但“发布”这个不可逆的公开动作,必须经过第二因素验证。对攻击者来说,即使偷到 stage-only token,也只能制造待审核的 staged version,不能直接污染 registry。

权限边界:不是只读令牌

根据 GitHub Changelog 的官方说明,Read and write (stage only) 令牌有三个关键特征:

  1. 允许工作流执行 npm stage publish,提交一个待审核的版本。
  2. 拒绝直接 npm publish,即使该令牌配置了 bypass 2FA 也不例外。
  3. 仍保留包的其他写权限,包括移动 dist-tags、废弃版本等。

这意味着 stage-only token 依然是 写权限令牌,而不是只读令牌。它可以改变 dist-tags,让用户安装到不同版本;也可以废弃某个版本,影响安装行为。因此,保护级别应与传统 write token 相同,不能因为“不能直接发布”就放松 secret 管理。官方 changelog 也明确提醒“Protect them with the same care as any other write token”。

版本要求与兼容性

官方给出的门槛是:npm CLI 11.15.0 或更高,Node.js 22.14.0 或更高。这是官方数据,不是社区推测。如果你的 CI 镜像还在使用 Node 20 或更旧的 npm,需要先升级。建议在本地和 CI 中执行以下检查:

# 版本检查(官方要求)
node --version   # 应 >= 22.14.0
npm --version    # 应 >= 11.15.0

# 旧做法:直接发布(stage-only token 会被拒绝)
npm publish

# 新做法:暂存版本,等待维护者 2FA 审核后发布
npm stage publish

需要注意的是,stage-only token 适用于已有 npm 包,但前提是对该包有 publish 权限、账户启用 2FA。官方 changelog 没有展开私有 registry 场景,这一点我会在“这次没核实的”部分单独说明。

迁移操作步骤

如果决定采用 stage-only token,最小迁移路径可以概括为:

  1. 在 npm 设置中创建 granular access token,权限选择 Read and write (stage only),范围覆盖工作流需要的包。
  2. 将新 token 存入 CI secret,替换掉原来的发布 token。
  3. 修改发布命令:把 npm publish 替换为 npm stage publish。
  4. 包维护者进入 npm 查看 staged version,使用 2FA 审核并批准发布。
  5. 删除或吊销旧的 bypass-2FA 发布 token。

以上步骤中,npm stage publish 是官方文档明确给出的命令,具体 UI 路径以 npm 实际界面为准。更完整的 GitHub Actions 配置示例,可以参考 npm staged publishing 文档。

与 trusted publishing 的关系

trusted publishing 是 npm 提供的更安全的自动化发布方案:通过 OIDC 让 GitHub Actions 与 npm 建立短期信任关系,不再需要长期 token。对已经完成 OIDC 配置的团队,直接使用 trusted publishing 仍然是最优解。

但现实是,很多团队因为自建 runner、企业网络策略、多平台支持等原因,短期内无法切换到 trusted publishing。官方 changelog 的措辞是:“If you can’t move to trusted publishing yet, stage-only tokens offer a migration path for token-based automation.” 因此,stage-only token 不是 trusted publishing 的替代品,而是为仍在使用 token-based automation 的团队提供的缓冲。

自己的判断 / 迁移清单

以下清单是笔者基于官方文档整理的判断,属于自己推算,不构成官方承诺。

  • [ ] 盘点所有 npm 发布 token,识别哪些是 bypass-2FA 的 granular access token。
  • [ ] 确认目标包的 publish 权限和 npm 账户 2FA 状态。
  • [ ] 升级 CI 的 Node.js 到 22.14.0+、npm CLI 到 11.15.0+。
  • [ ] 创建 stage-only token,权限范围只覆盖必要的包,不要给过大的组织级权限。
  • [ ] 在 CI 中用 npm stage publish 替换 npm publish,并删除旧的直接发布 token。
  • [ ] 通知包维护者新的审核流程:他们会收到 staged version 通知,需要用 2FA 批准。
  • [ ] 制定回滚方案:如果 stage publish 在 CI 中失败,应能快速定位是权限问题还是版本问题;但注意 2027-01 后旧方式不可用。
  • [ ] 评估是否可以在下一个迭代周期直接迁移到 trusted publishing,彻底去掉长期写 token。

额外提醒:stage-only token 仍可移动 dist-tags 和废弃版本,这些操作虽然不直接发布新版本,但可能影响用户安装结果。因此,它必须纳入 secret 管理和审计范围,不能当只读 token 看待。社区讨论入口可以在 npm community discussion category 找到,适合反馈迁移过程中的具体阻塞。

这次没核实的

  • 私有 registry 场景:官方 changelog 未明确说明 stage-only token 对私有 registry 的支持情况。本次写作材料中未提供足够来源,未能核实。
  • 第三方 CI 插件/action 兼容性:npm stage publish 是否与现有发布 action(如 npm-publish、changesets/action 等)无缝协作,未能找到官方说明。
  • 2027-01 移除 bypass-2FA 直接发布的具体执行方式:官方只说 targeting,具体是硬性拒绝、分阶段禁用还是有宽限期,细节尚未披露,未能核实。
  • 社区讨论中的实际迁移痛点:本次仅获得讨论区链接,未能逐条阅读并核实其中的用户反馈,因此没有引用任何社区二手数据。

参考来源

评论区

0 条评论

登录后可评论。

熬夜冠军 381 阅读