1664 字
8 分鐘

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建議做法
直接發佈 packagenpm 文件目前仍允許短期可維持,但安排 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 認證:

Terminal window
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,填入:

  1. Organization or user:GitHub 使用者或組織名稱。
  2. Repository:repository 名稱。
  3. Workflow filename:只填檔名,例如 publish.yml,不要填完整路徑;檔案必須位於 .github/workflows/,而且包含 .yml.yaml 副檔名。
  4. Environment name:若 release 使用 GitHub Environment,再填對應名稱。
  5. Allowed actions:選擇 npm publishnpm 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 publish

npm 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 publish

NPM_READ_TOKEN 只在安裝步驟存在,且應限制到必要 package/scope、設定到期日與 IP policy。不要因為安裝私有套件需要 token,就繼續給它 publish write 權限。這種最小權限切法,也比把一把長效 token 同時提供給 install、test 和 publish 更容易追蹤外洩範圍。

ENEEDAUTH 怎麼查#

如果 workflow 改完出現 ENEEDAUTH,按下面順序檢查:

  1. npm package 的 trusted publisher 是否選對 provider。
  2. Organization/user、repository 和 workflow filename 是否逐字相同;filename 只填 publish.yml,不要填 .github/workflows/publish.yml
  3. runner 是否為目前支援的 cloud-hosted runner。
  4. job 或呼叫鏈是否真的有 id-token: write
  5. 若使用 workflow_call,npm 文件指出 calling workflow 的名稱會參與驗證;parent 與 child workflow 都要檢查 OIDC 權限和設定。
  6. package 的 repository.url 是否精確指向要發佈的 GitHub repository,尤其是從 fork 發佈時。
  7. 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:About access tokens

npm Docs:Trusted publishing for npm packages

npm Docs:Requiring 2FA for package publishing and settings modification

npm Bypass 2FA 變了怎麼辦?用 Trusted Publishing 取代 CI 長效 token
https://laplusda.com/posts/npm-bypass-2fa-trusted-publishing/
作者
Zero
發佈於
2026-08-28
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。