2697 字
13 分鐘

npm Bypass 2FA 變了怎麼辦?用 Trusted Publishing 或 stage-only token

npm 在 2026 年 8 月起收緊啟用 Bypass 2FA 的 granular access token:這類 token 不能再執行變更 email/password、修改 2FA、管理 access token、增刪 package maintainer,以及 organization/team governance 等帳號身份與治理操作。9 月 18 日又推出可選的 stage-only token:CI 可以用 npm stage publish 把版本送進 staged publishing,卻不能用同一把 token 直接執行 npm publish。既有 token 不會因為這項新選項自動改變,但新的發佈流程應重新選擇適合的權限邊界。

Trusted Publishing 用 CI/CD 的 OIDC 身份換取短效、限定 workflow 的憑證,不需要把長效 npm publish token 放進 repository secret;stage-only token 則保留 token 認證,但把 CI 的第一步限制為送審。這篇把「現在的 token 還能做什麼」和「如何遷移發佈流程」分開,避免因為一次 API 失敗就把所有 token 撤掉,或把 read-only 安裝憑證誤當成 publish 憑證。

先分清 Bypass 2FA token 還能做什麼#

情境目前行為/限制建議做法
直接發佈 packagenpm 文件目前仍允許短期可維持,但安排 Trusted Publishing 遷移
使用 stage-only token只能 npm stage publish,不能直接 npm publishCI 送審,maintainer 檢視後以 2FA approve
修改 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 用途拆分。

stage-only token 和 Trusted Publishing 不是同一件事#

這三種認證解決的問題不同,先依 CI 的威脅模型選擇:

認證方式CI 能做什麼適合的控制點
Trusted Publishing以 OIDC 身份取得短效 publish 憑證不在 repository secret 保存長效 publish token,限制 repository、workflow 與 environment
stage-only token執行 npm stage publish,不能直接 npm publish讓 CI 先送審,由 maintainer 以 2FA 核准 staged version
read-only granular token安裝 private package 或讀取 registry只放在 npm ci/安裝步驟,不給 publish write 權限

stage-only token 仍是 token,外洩風險不會像 OIDC 一樣消失;它的價值是把「CI 可以送出候選版本」與「誰能把版本正式發佈」拆成兩個權限。Trusted Publishing 則是另一條不保存長效 publish token 的路徑,兩者可以依 package 和 release policy 分別使用。

把 CI 改成先送審#

如果 package 已存在、執行者有 publish access,且 package 已啟用 2FA,便可以用 staged publishing 把 release 分成 stage、review、approve 三步。先在 CI 檢查版本,再讓 stage-only token 執行第一步:

- name: Check toolchain
run: |
node --version
npm --version
- name: Stage package for review
run: npm stage publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_STAGE_TOKEN }}

目前 staged publishing 需要 npm CLI 11.15.0 或更新版本與 Node 22.14.0 或更新版本。npm stage publish 的結果會有 stage ID;maintainer 可以檢視 staged version,再用 npm stage approve <stage-id> 搭配 2FA 核准。實際操作前可用 npm stage list 和 npm stage view <stage-id> 確認候選版本狀態。這次文章更新沒有替你的 package 執行 stage 或 approve,範例是依官方文件整理的工作流程。

這條流程有幾個刻意的邊界:stage-only token 不能繞過審查直接 npm publish;staged publishing 針對已存在且你有 publish access 的 package;最後的 approve 仍需要 maintainer 的互動式 2FA。若團隊要完全移除長效 publish secret,應優先評估 Trusted Publishing,而不是把一般 write token 改名成 stage token。

先盤點 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 publish、npm stage publish,或兩者;至少要選一項。

欄位是精確比對,repository、workflow filename 和 environment 的大小寫、檔名都要與實際 workflow 一致。若你有多個 release workflow,可以為同一個 package 建立多組 trusted publishing configurations;任何一組符合 OIDC claims 就能授權,設定彼此獨立且採加法,不需要依賴評估順序。

每個 package 最多可設定 10 組 trusted publisher。新增設定前先把每組對應的 repository、workflow 與 environment 寫進 release inventory;既有連線的欄位不能直接修改,若要改內容,應刪除後重新建立。這能避免「為了修一個 environment,意外影響另一條 release pipeline」的操作風險。

多組設定要分清 stage 與 direct publish#

多組 trusted publishing configurations 並不代表每條 workflow 都應直接發佈。每個設定預設可以執行 staged publish;若要直接把版本送上公開 registry,仍要在該設定中明確允許 direct publish。staged publish 進入 malware scanning 期間不能核准,完成後才會出現在版本歷史中。

建議把權限拆成兩層:

  • release candidate workflow 只允許 stage,讓套件先經過掃描與人工確認。
  • 受保護 tag 或 production environment 才允許 direct publish,並搭配 environment approval。

若同一個 package 同時服務多個 repository,請確認每組設定的 workflow 與 environment 都能對應到唯一的部署責任;不要用一組過寬的設定來涵蓋所有 fork 或暫存 pipeline。

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 版本。

若把 workflow 改成 npm stage publish 後出現未知命令或版本錯誤,先確認執行的 npm CLI 是否至少是 11.15.0、Node 是否至少是 22.14.0,以及 token 是否真的被建立為 stage-only。不要只把 npm publish 改成 npm stage publish 就假設原本的 token 權限和 registry 設定會自動適用。

發佈後順手確認 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: stage-only token 和 Trusted Publishing 該選哪個?#

A: 如果希望 CI 保留 token 認證、但不能直接把版本發佈,可以選 stage-only token;如果希望 CI 不保存長效 publish token,則優先評估 Trusted Publishing。兩者都要搭配 package 權限、2FA、版本檢查與 release approval,不是只換一個 secret 名稱。

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:Staged publishing

npm Changelog:Multiple trusted publishing configurations for npm

GitHub Changelog:Stage-only npm tokens for safer automation

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

npm Bypass 2FA 變了怎麼辦?用 Trusted Publishing 或 stage-only token
https://laplusda.com/posts/npm-bypass-2fa-trusted-publishing/
作者
Zero
發佈於
2026-08-28
許可協議
CC BY-NC-SA 4.0