Post

npm Trusted Publishing (可信发布) 配置指南

如何配置 npm Trusted Publishing?本指南详述利用 OIDC 和 GitHub Actions 实现免密钥发布的最佳实践,解决 2FA 自动化发布难题并获取 Provenance 绿标。

npm Trusted Publishing (可信发布) 配置指南

TL;DR: npm Trusted Publishing (可信发布) 是一种基于 OIDC 协议的安全发包架构。它允许 GitHub Actions 在无需存储长效 NPM_TOKEN 的情况下,动态获取、临时鉴权,并自动点亮 npm 官网的 Provenance (来源证明) 绿标,完美规避 2FA 限制。


🌟 为什么 npm Trusted Publishing 是最佳实践?

在传统的 CI/CD 流程中,我们习惯在 GitHub Secrets 中存储长效 NPM_TOKEN。这种做法存在三个核心痛点:

  1. 凭证泄露风险:长效 Token 一旦泄露,攻击者可以滥用权限。
  2. 2FA 维护成本:开启 2FA 的账号无法直接配合传统 CI 鉴权。
  3. 缺乏来源透明度:用户无法确认代码确实源自特定 GitHub Workflow。

npm Trusted Publishing 解决了上述所有难题:实现“按需生成、瞬时失效”,不仅提升了安全性,还让你的包附带了 npm 社区最推崇的 Provenance 徽章。


🏗️ OIDC 配置流程概览

sequenceDiagram
    participant GH as GitHub Actions
    participant OIDC as GitHub OIDC Provider
    participant NPM as npm Registry
    
    GH->>OIDC: 请求签名 ID Token (携带 Repository/Workflow 信息)
    OIDC-->>GH: 返回 ID Token (JWT)
    GH->>NPM: 发送发布请求 + ID Token
    NPM->>NPM: 校验 Token 是否匹配 Trusted Publisher 配置
    NPM-->>GH: 授权通过,完成发布
    Note over NPM: 自动点亮 Provenance 绿标

🛠️ 黄金配置 (The Golden Config)

要走通 npm Trusted Publishing 流程,请严格校对以下三个文件:

1. package.json:必须的斜杠

这是最隐蔽的坑点。semantic-release 会严格校验 registry 地址。

1
2
3
4
5
6
{
  "publishConfig": {
    "access": "public",
    "registry": "https://registry.npmjs.org/" 
  }
}

[!IMPORTANT] SEO 关键细节:注意 registry 结尾的斜杠 /。如果是使用 semantic-release,缺少这个斜杠会导致 OIDC 鉴权逻辑失效,系统会回退去索要不存在的 NPM_TOKEN

2. .releaserc.json:开启 Provenance

在插件配置中显式声明开启来源证明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/npm",
      {
        "npmPublish": true,
        "provenance": true
      }
    ],
    "@semantic-release/github"
  ]
}

3. .github/workflows/release.yml:CI 权限分配

必须显式赋予 id-token 写入权限,这是触发 OIDC 的核心。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      issues: write
      pull-requests: write
      id-token: write # ⚠️ 核心:允许 Job 向 GitHub 请求 OIDC Token
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "lts/*" 
      
      - run: npm ci
      - run: npm run build
      
      - name: Semantic Release
        env:
          GITHUB_TOKEN: $
          # ⚠️ 绝对不要在这里传入 NPM_TOKEN!
        run: npx semantic-release@25 # ⚠️ 版本要求:必须 v25+ 才原生支持 OIDC

🚦 场景分叉:新包 vs 老包迁移

场景 A:发布一个全新的 npm 包

  1. 手动冷启动:本地执行 npm publish --access public 完成首次发布。
  2. 配置可信发布者:登录 npmjs.com,进入包的 Settings -> Trusted Publishers -> Add Publisher
  3. 绑定内容:仅填工作流文件名(如 release.yml)。

场景 B:旧包迁移 (删除 NPM_TOKEN)

  1. 绑定 Publisher:在 npm 侧完成 GitHub 绑定。
  2. 配置清理:从 CI 工作流中彻底移除 NPM_TOKEN 环境变量。
  3. 秘钥销毁:撤销 npm 官网上的长效 Token 以确保安全。

💣 常见报错排查手册

报错日志根本原因解决方案
EINVALIDNPMTOKENsetup-node 配置了干扰鉴权的 registry-url删除 setup-node 中的该配置。
ENONPMTOKEN多为 semantic-release 版本过低或 registry 漏了斜杠。使用 @25 版本,并确保 registry 末尾带 /
EBADENGINENode.js 版本太低。使用 node-version: "lts/*" (推荐 22+)。
EOTP仍在走旧的鉴权模式,或 Publisher 绑定失效。重新检查 id-token: write 权限和 npm 侧绑定信息。

💡 结语

配置 npm Trusted Publishing 是对软件供应链负责的体现。一旦配置成功,你将享受到免密钥运维的安全性,同时获得社区公认的 Provenance 绿标。


内链推荐:

This post is licensed under CC BY 4.0 by the author.