npm Trusted Publishing (可信发布) 配置指南
如何配置 npm Trusted Publishing?本指南详述利用 OIDC 和 GitHub Actions 实现免密钥发布的最佳实践,解决 2FA 自动化发布难题并获取 Provenance 绿标。
TL;DR: npm Trusted Publishing (可信发布) 是一种基于 OIDC 协议的安全发包架构。它允许 GitHub Actions 在无需存储长效
NPM_TOKEN的情况下,动态获取、临时鉴权,并自动点亮 npm 官网的 Provenance (来源证明) 绿标,完美规避 2FA 限制。
🌟 为什么 npm Trusted Publishing 是最佳实践?
在传统的 CI/CD 流程中,我们习惯在 GitHub Secrets 中存储长效 NPM_TOKEN。这种做法存在三个核心痛点:
- 凭证泄露风险:长效 Token 一旦泄露,攻击者可以滥用权限。
- 2FA 维护成本:开启 2FA 的账号无法直接配合传统 CI 鉴权。
- 缺乏来源透明度:用户无法确认代码确实源自特定 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 包
[!NOTE] 由于未发布的包在 npm 上还不存在,你无法提前配置 Trusted Publisher。因此,新包必须先进行一次本地手动发布(冷启动)。
- 本地手动冷启动
- Step 1: 登录并确认身份
1 2
npm login # 浏览器完成 2FA 登录 npm whoami # 必须输出你的 npm 账号 (例如 rbbtsn0w)
- Step 2: 发布前 Dry-run 自检
在不真正上传的前提下,预检打包内容与编译流程:1
npm publish --dry-run --access public --tag alpha
[!TIP]
prepare生命周期钩子会在此阶段触发npm run typecheck,作为发布前的编译与类型检查门禁。 - Step 3: 正式手动发布
1
npm publish --access public --tag alpha
--access public:Scoped 包默认是私有的(Private),必须显式指定为公开(Public)。--tag alpha:关键步骤,避免将首个处于测试或开发阶段的版本设为latest。
- Step 4: 补齐 Git Tag
手动标记版本并推送,为后续semantic-release的自动化接管打下基础:1 2
git tag v0.1.0-alpha.1 git push origin v0.1.0-alpha.1
- Step 1: 登录并确认身份
配置可信发布者 (Trusted Publisher)
首次手动发布成功后,登录 npmjs.com,进入该包的 Settings -> Trusted Publishers -> Add Publisher。- 绑定 GitHub 仓库
仅需填写你的 GitHub 组织/用户、仓库名,以及触发发布的工作流文件名(例如release.yml)。
场景 B:旧包迁移 (彻底移除 NPM_TOKEN)
若该包在 npm 上已存在,可以直接通过以下顺序平滑迁移至免密钥发布,确保 CI/CD 流程不中断:
- 绑定 Trusted Publisher:在 npm 侧对应包的后台完成 GitHub 仓库绑定。
- 清理 CI 配置:从 GitHub Actions 的
.yml文件或项目 Secrets 中,彻底移除NPM_TOKEN环境变量。 - 销毁历史密钥:确认 CI 自动发布成功后,登录 npm 官网,撤销之前生成的所有长效发布 Token,实现安全闭环。
💣 常见报错排查手册
| 报错日志 | 根本原因 | 解决方案 |
|---|---|---|
EINVALIDNPMTOKEN | setup-node 配置了干扰鉴权的 registry-url。 | 删除 setup-node 中的该配置。 |
ENONPMTOKEN | 多为 semantic-release 版本过低或 registry 漏了斜杠。 | 使用 @25 版本,并确保 registry 末尾带 /。 |
EBADENGINE | Node.js 版本太低。 | 使用 node-version: "lts/*" (推荐 22+)。 |
EOTP | 仍在走旧的鉴权模式,或 Publisher 绑定失效。 | 重新检查 id-token: write 权限和 npm 侧绑定信息。 |
💡 结语
配置 npm Trusted Publishing 是对软件供应链负责的体现。一旦配置成功,你将享受到免密钥运维的安全性,同时获得社区公认的 Provenance 绿标。
内链推荐:
