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 就在別處發布,這已經切掉一種很常見的攻擊方式。