配了三年 npm 发包,今天才知道那个 legacy token 一直是个定时炸弹

2026 年 3 月,axios 的维护者被攻击者拿下账号,发布了两个带后门的版本:axios@1.14.1 和 axios@0.30.4。每周 8300 万次下载、200 多万个依赖它的项目,成了 JavaScript 史上最严重供应链攻击之一。

但最让人唏嘘的是:axios 当时已经配好了 SLSA Level 2,已经启用了 npm OIDC Trusted Publishing,已经在每次发布时附上了可验证的 provenance 签名。

什么都没拦住。因为攻击者用的不是 CI/CD 管道,而是一个被遗忘在某个角落的 legacy classic token。

npm 的认证优先级是个坑

当你同时给一个账号配置了 OIDC Trusted Publishing 和一个 classic token,npm 的认证优先级是:classic token 在前,OIDC 在后。攻击者不需要绕过 CI,不需要伪造 provenance,只需要一个 2020 年生成的、从来没改过密码的 Automation Token。

这个优先级规则在官方文档里藏得很深,但它直接让所有「配好了 provenance 就以为安全了」的团队裸奔。

你现在能做的事,三步

第一步:检查你有没有 legacy token 在生效

去 npmjs.com/settings/tokens,看有没有 Automation 类型的 token。如果有,问自己:这个东西还能不能用?要不要留着?还是早就该删了?

第二步:切到 OIDC,把 token 删掉

.github/workflows/publish.yml 改成这样:

permissions:
  contents: read
  id-token: write  # 让 npm 能拿 OIDC token

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
          registry-url: "https://registry.npmjs.org"
      - run: npm ci
      - run: npm publish --provenance --access public

把 NODE_AUTH_TOKEN 从 Secrets 里删掉,改用 OIDC。发布完去 npm 把那个 classic token revoke 掉。

第三步:在 CI 里验证依赖的 provenance

npm audit signatures

这条命令检查 node_modules 里每个包的签名和 provenance,任何没经过 CI 发布、没有可验证出处的包都会报出来。把它加到 CI 的必须通过的检查里,少则 10 秒,不影响正常构建。

配好了 OIDC 之后,要做的就一件事

去 npmjs.com/settings/tokens,把你那个 classic token revoke 掉。不是 disable,是 revoke。disable 了还在,被攻击者拿到还是能用。

2026 年的供应链安全不需要你懂密码学,但需要你把那些历史遗留的 token 当成真正的攻击面来处理。

附:npm 认证优先级规则官方说明在 npm 文档的 Authentication 章节,OIDC Trusted Publishing 配置见 npmjs.com/settings/tokens 下的 Publishing Access 面板。

评论区

0 条评论

登录后可评论。

阿监·前端工程化 1583 阅读