繁體中文English
jason's blog關於網頁標準、瀏覽器與前端開發的觀察筆記

文章分類: 資訊安全

npm Classic Token 退場與套件發布安全

npm Classic Token 退場後,套件發布流程為什麼要走向短效憑證。

發布 2025/11/05

npm 宣布 classic token 退場時,我一半覺得「早該如此」,另一半又立刻想到:那幾條很久沒人碰的發布 workflow 大概又要壞了。這種安全更新就是有點討厭,它明明在做對的事,卻一定會挑你準備 release 的時候提醒你,某把三年前存進 CI 的鑰匙其實早就不該留到現在。

npm Classic Token 很方便,但它也可能長時間有效,而且常被放進 CI 環境。一旦 token 外洩,攻擊者就有機會用維護者身分發布被動過手腳的套件。

npm 停止建立 classic token,是把發布流程推向短效 token、2FA 和 Trusted Publishing。Trusted Publishing 透過 CI 平台的身分來確認這次發布,不必另外存放一把長期有效的 npm 密鑰。

對只會安裝套件的人來說,這似乎很遠;但熱門套件只要有一個維護者帳號被接管,就可能影響大量網站。發布流程麻煩一點,換來的是整個生態少一個容易被利用的入口。

Trusted Publishing 少存了一個祕密

傳統 CI 發布時,要先把 npm token 存進 GitHub Actions secret。Trusted Publishing 改由 GitHub Actions 提供短時間的身分證明,npm 再確認是哪個 repository、哪個 workflow 正在發布。流程跑完後,不會留下一把能被重複使用好幾個月的鑰匙。

它仍然不是萬靈丹。workflow 本身被改掉、維護者帳號被接管,一樣可能出事。但攻擊者比較難只靠偷到一段 token 就在別處發布,這已經切掉一種很常見的攻擊方式。

套件作者遷移時可以先確認 CI provider 是否被 npm 支援,再限制允許發布的 repository、workflow 與 environment。權限描述得愈精確,其他分支或 fork 就愈難冒充正式發布流程。

切換前我會先在測試 package 走完整個流程,尤其確認 tag、provenance 和 prerelease 的行為。發布權限通常平常碰不到,一出錯卻剛好是在準備 release 的時間點;先做一次不影響正式套件的演練,比在半夜回頭重建 token 輕鬆很多。

另外,Trusted Publishing 解決的是「CI 如何向 npm 證明身分」,不是「誰可以修改 CI」。保護預設分支、要求 workflow 檔案由 code owner review,同樣是發布流程的一部分。