npm 供應鏈防禦

最近每隔幾週甚至幾天就看到新的供應鏈攻擊的新聞,最多的是 npm,再來 PyPI 也不少,別的生態系平常用得少就沒在關注了。

趁著這主題正夯,把拖稿半年的文章寫完了,這邊先整理個精華版。

當你執行 npm install express 的時候,npm 會先去看 express 最新的版本是多少,接著下載。然後呢,express 本身也依賴很多其他套件嘛,就會根據 express 的 package.json 去找這些套件,然後再遞迴去找所有依賴,全部都下載下來。

而 express 的 package.json 可能是寫說「某個套件 2.x.x 版本我都接受」,因此若你安裝的時候剛好有個駭客幫某個套件發了新版,你就自動下載到最新版,然後就 gg 了。

之所以下載即 gg,是因為 npm 的套件可以寫一些 scripts,例如說 postinstall,安裝完就會自動執行這個 script,所以套件就寫個惡意腳本放到 postinstall,你下載完執行,就被駭了。

但這功能其實是可以關掉的,關掉就少了一個攻擊面,雖然還是有可能下載到惡意套件,但至少不會在下載後就直接執行惡意程式碼。

話雖如此,能不下載到惡意套件當然是最好的。

目前最好的防範方式是設置一個 min release age 的參數,可以加一個「延遲時間」,例如說 3 天好了,代表你只允許下載 3 天前發布的套件。由於現在也不少資安公司在做防護,所以惡意套件通常 1 天內就會被發現而且下架,3 天應該滿夠的。

再者,如果不是第一次安裝,也能透過 lockfile 去鎖定版本(這很重要),確保每次下載的版本是一樣的,不會不小心下載到最新版。

那把 scripts 關掉又把 min release age 設定成 3 天就安全了嗎?還沒,因為除了可以去 registry 下載套件之外,其實也能從第三方 URL 跟 git URL 去下載,這兩個又會有各自的其他問題。

昨天寫了一篇部落格文章,想仔細了解的可以看一下,不用留言任何關鍵字,我也不會私訊你什麼大禮包,你點一下就看得到了。

懶得看的話,最懶人的做法是改用最新版 v11 的 pnpm,它預設的設定就幫你擋了很多東西,怕的話再加裝個 sfw(socket firewall),至少能擋掉絕大部分的攻擊。

評論