npm Bypass 2FA 變了怎麼辦?用 Trusted Publishing 取代 CI 長效 token
npm 在 2026 年 8 月起收緊啟用 Bypass 2FA 的 granular access token:這類 token 不能再執行變更 email/password、修改 2FA、管理 access token、增刪 package maintainer,以及 organization/team governance 等帳號身份與治理操作。npm 文件目前仍表示它們可以直接 publish,但 CI/CD 不應再把長效 write token 當成唯一方案,應改評估 Trusted Publishing。
Trusted Publishing 用 CI/CD 的 OIDC 身份換取短效、限定 workflow 的憑證,不需要把長效 npm publish token 放進 repository secret。這篇把「現在的 token 還能做什麼」和「如何遷移發佈流程」分開,避免因為一次 API 失敗就把所有 token 撤掉,或把 read-only 安裝憑證誤當成 publish 憑證。
先分清 Bypass 2FA token 還能做什麼
| 動作 | 啟用 Bypass 2FA 的 token | 建議做法 |
|---|---|---|
| 直接發佈 package | npm 文件目前仍允許 | 短期可維持,但安排 Trusted Publishing 遷移 |
| 修改 email、password 或 2FA 設定 | 不允許,必須互動式 2FA | 用 npm 網頁或互動式 CLI 完成 |
| 建立、提升或管理 access token | 不允許,必須互動式 2FA | 由管理者在有互動式驗證的環境操作 |
| 增刪 package maintainer、組織與 team governance | 不允許,必須互動式 2FA | 走 npm 的互動式管理流程 |
| CI/CD publish | 不建議再依賴長效 write token | 使用 Trusted Publishing;私有依賴另備 read-only token |
這項調整不等於所有既有 token 都在同一天失效,也不等於必須立刻輪替全部 secrets。先列出 token 的 package scope、權限、到期日、使用 workflow 和最後使用時間,再按 publish 與 install 用途拆分。
先盤點 workflow 裡的 npm 認證
在 repository 搜尋容易洩漏或長期存在的 publish 認證:
rg -n 'NODE_AUTH_TOKEN|NPM_TOKEN|npm publish|registry\.npmjs\.org|npmrc' \ .github package.json .npmrc 2>/dev/null針對每一條 workflow 記錄:
- publish 的 package 與 registry 是否是 npm public registry。
- token 是只讀安裝,還是具有 write/publish 能力。
- runner 是 GitHub-hosted,還是 self-hosted。
- workflow 是直接觸發
npm publish,還是由workflow_call呼叫另一個 workflow。 - package 是否有 private dependencies,讓安裝仍需要另一種認證。
盤點結果也能幫你決定遷移順序:先把公開 package 的 release workflow 改成 OIDC,再處理需要 read-only token 安裝私有套件的 workflow。
在 npm package 設定 Trusted Publisher
以 GitHub Actions 為例,進入 npmjs.com 的 package settings,找到 Trusted Publisher,選擇 GitHub Actions,填入:
- Organization or user:GitHub 使用者或組織名稱。
- Repository:repository 名稱。
- Workflow filename:只填檔名,例如
publish.yml,不要填完整路徑;檔案必須位於.github/workflows/,而且包含.yml或.yaml副檔名。 - Environment name:若 release 使用 GitHub Environment,再填對應名稱。
- Allowed actions:選擇
npm publish、npm stage publish,或兩者;至少要選一項。
每個 package 同一時間只能設定一個 trusted publisher。欄位是精確比對,repository、workflow filename 和 environment 的大小寫、檔名都要與實際 workflow 一致。
GitHub Actions 最小 OIDC workflow
官方 npm 文件要求 workflow 具備 id-token: write,讓 GitHub Actions 能產生 OIDC ID token。範例可以從一個只在 version tag 執行的 workflow 開始:
name: Publish package
on: push: tags: - 'v*'
permissions: id-token: write contents: read
jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' registry-url: 'https://registry.npmjs.org' package-manager-cache: false - run: npm ci - run: npm test - run: npm publishnpm publish 這一步不需要 NODE_AUTH_TOKEN。npm CLI 會在支援的 OIDC 環境中優先使用 Trusted Publishing,並取得只對該次 workflow 有效的短效憑證。把原本的 publish token 直接留在環境變數裡,反而會讓你難以確認流程到底走 OIDC 還是傳統 token。
Trusted Publishing 目前需要 npm CLI 11.5.1 或更新版本與 Node 22.14.0 或更新版本。官方支援 GitHub-hosted runners、GitLab.com shared runners 和 CircleCI cloud;self-hosted runner 目前尚未支援。
私有依賴和 publish 認證要拆開
Trusted Publishing 只處理 publish,不會替 npm ci 下載 private dependencies。這種 workflow 可以用 read-only granular token 安裝依賴,publish 仍交給 OIDC:
- uses: actions/setup-node@v6 with: node-version: '24' registry-url: 'https://registry.npmjs.org' package-manager-cache: false
- name: Install private dependencies run: npm ci env: NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
- name: Publish with OIDC run: npm publishNPM_READ_TOKEN 只在安裝步驟存在,且應限制到必要 package/scope、設定到期日與 IP policy。不要因為安裝私有套件需要 token,就繼續給它 publish write 權限。這種最小權限切法,也比把一把長效 token 同時提供給 install、test 和 publish 更容易追蹤外洩範圍。
ENEEDAUTH 怎麼查
如果 workflow 改完出現 ENEEDAUTH,按下面順序檢查:
- npm package 的 trusted publisher 是否選對 provider。
- Organization/user、repository 和 workflow filename 是否逐字相同;filename 只填
publish.yml,不要填.github/workflows/publish.yml。 - runner 是否為目前支援的 cloud-hosted runner。
- job 或呼叫鏈是否真的有
id-token: write。 - 若使用
workflow_call,npm 文件指出 calling workflow 的名稱會參與驗證;parent 與 child workflow 都要檢查 OIDC 權限和設定。 - package 的
repository.url是否精確指向要發佈的 GitHub repository,尤其是從 fork 發佈時。 - Trusted Publisher 設定是否真的套用到目前 package;npm 不會在保存設定時替你驗證所有欄位。
若只有 npm ci 失敗,先分辨它是 private dependency 的 read token 問題,不要直接替 publish OIDC 加回長效 write token。若只有 npm publish 失敗,再查看 job 實際執行的 workflow、OIDC permission 和 npm CLI/Node 版本。
發佈後順手確認 provenance
從 GitHub Actions 或 GitLab CI/CD 使用 Trusted Publishing 發佈 public repository 的 public package 時,npm 會自動產生 provenance attestations,不需要在 npm publish 另外加 --provenance。CircleCI Trusted Publishing 目前不會產生 provenance,不能把三種 provider 的結果混為一談。
發佈完成後可檢查 package 頁面的 provenance 資訊,並把 trusted publisher 設定、release tag protection 和 deployment environment approval 一起納入審查。Trusted Publishing 降低長效 write token 的風險,但不會替你限制誰能建立 release tag,也不會取代測試與 artifact review。
這種供應鏈邊界也可以和 pnpm 的 minimumReleaseAge 與 trustPolicy 分開看:npm Trusted Publishing 解決「誰能發佈」,pnpm policy 解決「安裝時接受什麼依賴」,兩者不是互相替代的設定。
常見問題
Q: Bypass 2FA token 現在完全不能用了嗎?
A: 不是。npm 文件目前表示它仍可直接 publish,但從 2026 年 8 月起不能執行多項帳號身份與治理操作。CI/CD 應把這個「目前還能 publish」視為遷移緩衝,而不是長期安全策略。
Q: Trusted Publishing 可以取代安裝 private package 的 token 嗎?
A: 不能完全取代。Trusted Publishing 針對 publish;npm ci 讀取 private dependencies 仍可能需要 read-only granular token。把兩種用途分開,才不會讓安裝失敗時重新授予 publish 權限。
Q: self-hosted GitHub runner 可以使用 npm Trusted Publishing 嗎?
A: 目前不行。npm 文件列出的支援範圍是 GitHub-hosted runners、GitLab.com shared runners 與 CircleCI cloud;self-hosted runners 尚未支援。若不能改用支援的 runner,應先保留更嚴格限制與輪替週期的傳統 token 流程。
參考資料:
npm Docs:Trusted publishing for npm packages
npm Docs:Requiring 2FA for package publishing and settings modification
回報錯字、失效連結,或告訴我你想看的延伸主題。