6 月 9 日,GitHub 在官方 Changelog 發布〈Upcoming breaking changes for npm v12〉,預告 7 月上線的 npm v12 將把三件事改成「預設禁止」:依賴套件的 preinstall/install/postinstall scripts 不再自動執行、Git 依賴與遠端 URL tarball 依賴不再解析,除非你逐項明確允許。接下來幾天 The Hacker News、BleepingComputer 接連跟進報導,這是 npm 史上對預設行為最大的一次外科手術。
要理解這刀為什麼砍得這麼深,得回看十年的供應鏈攻擊史:2018 年 event-stream 後門、2021 年 ua-parser-js 挖礦木馬,到 2025 年自我複製的 Shai-Hulud 蠕蟲——幾乎每一次的感染入口都是同一個:postinstall script 在你打 npm install 的瞬間,以你的權限執行任意程式碼。過去的防線是開發者自律加上 --ignore-scripts 旗標,但那是 opt-in;npm v12 把方向整個翻過來,從「預設執行、自己關」變成「預設封鎖、自己開」。
影響範圍沒有懸念:npm registry 每週服務數百億次下載,任何一個有 node_modules 的專案都在射程內——包括每一個用 Vite 打包前端的 Laravel 專案。依賴原生編譯(node-gyp)、sharp、esbuild、husky 這類靠 install script 工作的套件,七月起在乾淨環境會直接不執行 script,CI pipeline 與 Docker build 是第一波斷裂點。
下面拆解三項變更的確切行為、npm approve-scripts 的遷移指令,以及 npm 12 與 pnpm、Bun、Yarn 的取捨。
技術細節 + CLI
- 依賴的 install scripts 預設不執行(你自己專案 root 的 scripts 不受影響)
- Git 依賴(直接或間接)需
--allow-git才解析 - 遠端 URL tarball 依賴需
--allow-remote才解析
依 npm 官方文件,建議的遷移路徑是先升級到 npm 11.16.0 之後的版本,跑一次安裝看警告,再逐項放行:
# 先模擬 v12 行為,今天就能測
npm install --ignore-scripts
# 升級到 11.16.0+,安裝時會列出「將被封鎖」的 scripts
npm install -g npm@11
npm install
# 檢視待審核的套件 scripts,放行你信任的
npm approve-scripts --allow-scripts-pending放行結果會寫進 package.json,進版本控制、過 code review——信任決策第一次變成可稽核的 diff。
三類讀者的立刻行動
- 工程師:本週在 CI 加一條
npm install --ignore-scripts的 job,列出會壞的套件清單;檢查 sharp、esbuild、puppeteer、husky 等重度依賴 install script 的套件。 - 技術負責人:把「npm 12 相容性」排進 6 月 sprint;Docker base image 與 CI runner 的 npm 版本要釘住,避免 7 月被動升級炸掉部署;同步盤點 lockfile 內的 Git/URL 依賴存量。
- 創業者/接案商:問你的維護廠商一句話:「我們的專案七月 npm 12 上線後還能 build 嗎?」答不出來,就是你需要維護合約的證據。
比較與權衡
| 方案 | 優點 | 缺點 | 遷移成本 |
|---|---|---|---|
| npm 12(預設封鎖) | 官方標準、allow 清單進 package.json 可稽核 | 7 月起 CI 首當其衝、生態適應期混亂 | 低:跑 approve-scripts、改 CI(0.5-1 工作日/專案) |
| pnpm 10+ | 2025 年初起即同樣預設、生態驗證過 | lockfile 不相容 npm | 中:換 lockfile 與 CI 快取(1-2 工作日) |
| Bun | 安裝極快、預設只信任白名單套件 scripts | runtime 相容性仍有邊角、企業採用保守 | 中-高:需驗證整條 build chain |
| Yarn Berry | PnP 模式根本沒有 node_modules 可感染 | 學習曲線陡、舊套件相容問題多 | 高:架構級遷移(3-5 工作日起) |
不會告訴你的事
- 封鎖 install scripts 擋不住 require-time 攻擊:惡意程式碼搬進模組本體,在你
import的那一刻照樣執行。這次砍掉的是「最方便」的入口,不是「唯一」的入口。 - 「允許清單疲勞」是新風險:當開發者習慣無腦 approve,攻擊者只要寄生在「大家一定會放行」的熱門套件相依樹裡就好。安全預設值轉移了攻擊成本,沒有消滅它。
未來 3 個月會發生什麼
7 月 npm 12 GA 後,預期第一週會出現大量 CI 災情文與「怎麼全部放行」的錯誤教學;主流框架(Next.js、Vite、Laravel 生態的 npm 工具鏈)會陸續發布官方 allow 清單建議。觀察指標:npm approve-scripts 的 DX 是否好用到讓人不想繞過,以及 pnpm 是否藉機再吃一波市佔。
常見問題 FAQ
我的專案會不會壞?怎麼最快確認?
在本機或 CI 跑 npm install --ignore-scripts 後執行完整 build 與測試。會壞的幾乎都集中在原生編譯(node-gyp)與下載 binary 的套件(sharp、puppeteer、esbuild)。
我自己專案的 build script 會被擋嗎?
不會。封鎖的是「依賴套件」的 lifecycle scripts;你專案 root 的 package.json scripts(dev、build、postinstall)照常執行。
用 pnpm 的團隊需要做什麼?
基本不用動,pnpm 10 起已是同樣的預設。這次是 npm 向 pnpm 的安全模型看齊。
Laravel + Vite 專案受影響嗎?
受影響的是前端依賴層。Vite 本身無 install script 依賴問題,但其相依樹中的 esbuild 等需要放行;上線前先在 staging 驗證 npm ci 全流程。
我的觀點
主流敘事是「npm 終於安全了」,我的判斷相反:最危險的窗口正是變更上線後的前六個月。安全預設值給了團隊「已經處理完」的錯覺,但攻擊面只是移到 require-time 與 allow 清單的審核品質上;而大量團隊會在 CI 壞掉的壓力下,用「全部放行」的 workaround 把防線自己拆掉——壓力下做的安全決策,通常是最差的安全決策。對 ScriptWalker 的業務啟示:這是一個有明確截止日(7 月)的健檢商機——對所有維護合約客戶主動提供「npm 12 相容性掃描」,一次掃描、一張報告、一個 approve 清單 PR,把一次性的生態變動轉成可收費的看護價值。