**一週內三次。**三。次。到這個時候,我開始覺得NPM代表「永無止境的入侵機器」,因為天啊安全漏洞——我們又有另一個供應鏈攻擊,而這個絕對精彩絕倫地邪惡。
認識Shai-Hulud(是的,這是實際的代號——以《沙丘》中的巨型沙蟲命名,因為顯然駭客現在開始玩科幻梗了)。這不是你平常「糟糕,我下載了一個惡意軟體包」的情況。不,不,不。這是一場自我複製的數位疫情,像是在試圖贏得「最有創意的方式毀掉所有人的一天」諾貝爾獎一樣從一個倉庫傳播到另一個。
讓安全工程師哭泣的劇情轉折
還記得惡意軟體很簡單的美好舊日嗎?下載壞軟體包,惡意軟體竊取你的令牌,遊戲結束。Shai-Hulud說「拿著我的啤酒」,然後決定以最糟糕的方式創新。
這個寶貝不只是竊取你的憑證然後收工。它用你被竊取的令牌去感染其他倉庫。就像如果一個竊賊不只是搶劫你的房子,還用你的鑰匙去搶劫你所有的鄰居,然後他們的鑰匙被偷去搶劫他們的鄰居,以此類推直到你整個城市變成一個巨大的犯罪現場。
Shai-Hulud攻擊中被入侵的主要軟體包包括@ctrl/tinycolor、@crowdstrike/falcon-shoelace、ngx-bootstrap和其他180多個。攻擊針對多個維護者的流行庫,從UI元件到安全工具,展示了這次供應鏈入侵的巨大範圍。來源:OX Security
攻擊始於一個謙虛的、已被棄用的軟體包叫做rxnt-authentication,它已經很久沒有更新了。然後突然——劇情轉折!——版本0.0.5和0.0.6像數位幽靈一樣出現,攜帶著它們的惡意載荷進入野外。
數位達爾文主義的解剖
這是技術上既迷人(又可怕)的地方:
步驟1:釣魚鉤 某個可憐的開發者可能收到了一封令人信服的電子郵件:「嘿,你需要為了安全原因更新你的npm令牌!點擊這裡!」*點擊。*遊戲結束。
步驟2:特洛伊木馬 攻擊者使用修補更新推送惡意版本(因為顯然我們仍然沒有學會不自動升級修補版本——說真的,各位,鎖定你們的版本)。
步驟3:數位寄生蟲 一旦安裝,軟體包運行一個安裝後腳本,部署一個叫做「Truffle Hog」的東西——順帶一提,這既是一個優秀的名字,也是一個合法的安全工具,用於掃描洩露的憑證。除了現在它被用於邪惡而不是善良。就像看著超人變成銀行劫匪。
步驟4:病毒式傳播 這是傑作:不只是把你的令牌外洩到某個遠端伺服器,Shai-Hulud立即開始處理你的GitHub倉庫。它:
- 更新你的CI/CD管線
- 修改你的package.json檔案
- 發布你的軟體包的新「修補」版本
- 在新版本中包含它自己
沖洗,重複,指數級增長。就像一個傳銷騙局,但是是惡意軟體的。
數字遊戲(劇透:我們正在輸)
攻擊始於40個被入侵的軟體包。幾小時內,這個數字跳到180多個。按這個增長率,到下週我們會有比可觀測宇宙中原子數量還多的被感染軟體包。(好吧,那是誇張,但指數級增長確實很可怕。)

但等等——還有更多!在受害者中,我們有諷刺的皇冠珠寶:CrowdStrike!
是的,你沒看錯。同一個銷售安全解決方案並在今年早些時候給我們帶來藍屏死機大事件的CrowdStrike——鼓聲請——現在正在通過他們的npm軟體包意外分發蠕蟲攻擊。具體來說,攻擊入侵了:
@crowdstrike/commitlint(版本8.1.1、8.1.2)@crowdstrike/falcon-shoelace(版本0.4.1、0.4.2)@crowdstrike/foundry-js(版本0.19.1、0.19.2)@crowdstrike/glide-core(版本0.34.2、0.34.3)@crowdstrike/logscale-dashboard(版本1.205.1、1.205.2)@crowdstrike/tailwind-toucan-base(版本5.0.1、5.0.2)
你真的編不出這種東西。宇宙有幽默感,而那種幽默感顯然非常、非常黑暗。
「Tiny Color」悲劇
另一個值得一提的受害者是流行的tiny-color軟體包,它通過維護者被入侵的憑證被攻擊。版本4.11和4.12被感染,但在一個美麗的挑釁幽默行為中,安全版本被發布為…4.20。
完美給做出那個版本號決定的人。在混亂中,有人還是有時間開個玩笑。
我們創造的依賴地獄
這次攻擊突顯了我們一直故意忽視的東西:我們的依賴樹太瘋狂了。我們正在導入整個庫來使用單一函數。需要填充字串?導入left-pad。需要檢查某東西是不是數字?導入is-number。需要把HSV轉換成RGB?再導入一個有47個傳遞依賴的軟體包。
在AI時代,你可以直接問ChatGPT「幫我寫一個left-pad函數」並在3秒內得到一個可運行的實現,為什麼我們還在玩依賴俄羅斯輪盤?
自動更新成癮
我們能談談自動更新修補版本嗎?**停止吧。**就…停止。這是今年第三個依賴自動修補版本更新的重大攻擊了。現在是2025年,我們還在一遍又一遍地犯同樣的錯誤。
鎖定你的版本。是的,這是更多的工作。是的,你會錯過一些錯誤修復。但你知道你不會錯過什麼嗎?意外安裝自我複製的惡意軟體。
這是事情:即使你是個好公民並鎖定你的版本,你仍然很脆弱,因為軟體包管理器是遞迴的噩夢。你依賴軟體包A,它依賴軟體包B,軟體包B自動更新以包含惡意軟體,然後它感染你的專案。
依賴一直往下延伸,每一層都是潛在的攻擊向量。
現實世界的影響
這不只是理論上的。真實的公司、真實的專案、真實的生產環境都被攻擊了。攻擊針對:
- 暴露GitHub令牌的開發環境
- 具有發布憑證的CI/CD管線
- 快取認證的本地開發者機器
如果你有npm令牌放在任何地方——在你的環境變數中、你的CI配置中、你瀏覽器的儲存密碼中——Shai-Hulud正在來找它們。
防禦策略(或:如何不被入侵)
1. 鎖定一切
{
"dependencies": {
"some-package": "1.2.3", // 確切版本,沒有波浪號,沒有插入號
"another-package": "4.5.6"
}
}
2. 像你的生命取決於它一樣審計
虔誠地運行npm audit。設置自動化依賴掃描。把你的package.json當作包含核發射代碼一樣對待。
3. 最小化依賴 問自己:「我真的需要一個軟體包來檢查一個數字是否是奇數嗎?」答案可能是不需要。
4. 輪換你的令牌 如果你最近沒有輪換你的npm令牌,現在就做。如果你有2019年的令牌還在四處漂浮,昨天就刪除它們。
5. 監控你的軟體包 如果你維護軟體包,設置意外發布的警報。如果版本3.1.4突然出現而你沒有發布它,那是德州大小的紅旗。
更大的圖景
Shai-Hulud代表了供應鏈攻擊的進化。它不只是惡意軟體——它是自我傳播的惡意軟體。這是當攻擊者研究網路效應並將其應用於網路犯罪時會發生的事情。
這次攻擊成功是因為它利用了幾個系統性問題:
- 對自動化依賴更新的過度依賴
- 整個生態系統中糟糕的令牌衛生
- 現代軟體包管理的互聯性質
- 開發者隱式信任修補更新的傾向
這對未來意味著什麼
我們處於一個轉折點。要麼我們集體認真對待供應鏈安全,要麼我們會看到更多像這樣的攻擊。Shai-Hulud證明了npm的生態系統可以被武器化成一個分散式攻擊平台。
下一次攻擊可能更糟。它可能針對Docker映像,或Python軟體包,或Rust crates。它可能持續更久,傳播更快,或造成更多損害。
一線希望
有一些好消息:這次攻擊被相對快速地發現,受影響的軟體包正在被清理,安全社群正在迅速回應更好的檢測工具和實踐。
而且,無論我們想不想,我們都正在接受供應鏈安全的速成課程。沒有什麼比看著你的整個生態系統被自我複製的軟體包病毒攻陷更能教會防禦性程式設計的了。
艱難學到的教訓
- 自動更新很方便,直到它們變成災難
- 每個依賴都是潛在的攻擊向量
- 令牌輪換不是可選的——它是必需的
- 寫自己的實用函數的成本現在比導入它們的風險低
- 安全不是別人的問題——它是每個人的問題
最後的想法
在我寫這篇文章的時候,Shai-Hulud的清理工作正在進行中。軟體包正在被修補,令牌正在被輪換,世界各地的開發者正在就他們的依賴管理實踐進行不舒服的對話。
這次攻擊在其簡單性上很出色,在其有效性上很可怕。它把npm最大的優勢——其互聯的生態系統——變成了其最大的弱點。
但這是事情:我們可以從這裡學習。我們可以建立更好的工具,實施更好的實踐,創造更有彈性的系統。或者我們可以忽視教訓,等待Shai-Hulud 2.0。
選擇權在我們手中。讓我們做出正確的選擇。
保持警惕,鎖定你的依賴,記住:在軟體包管理的世界裡,偏執不是bug——它是功能。
資源:
負責任地更新你的軟體包,朋友們。生態系統取決於此。