你 team 正在開發一個影像分類模型, teammate 推了一個 PR:「加上 lightning 的 distributed training」,你 review 後 pip install 就放行了。幾分鐘後,GitHub Action 噴出一個奇怪的錯誤 — 一個叫 EveryBoiWeBuildIsaWormBoi 的 repo 突然出現在你的組織下。你的動作沒停,但你的 CI token、AWS 金鑰和 GitHub Secrets 已經在一秒內被加密打包,送往三個不同的 C2 通道。
這不是科幻劇本。這是 2026 年 4 月 30 日真實發生的事 — PyPI 套件 lightning(一個每月數百萬下載的深度學習框架)的 2.6.2 和 2.6.3 版本被植入後門,而攻擊者的手法,讓這次事件成為 AI 供應鏈安全的新分水嶺。
根據 Semgrep 的安全研究團隊發布的詳細分析,這波攻擊的操弄者與去年「Mini Shai-Hulud」行動是同一威脅組織。如果說之前那次是試水溫,這次就是直接拔刀。
這不是一般的依賴汙染
PyPI 上的供應鏈攻擊並不新鮮。2023 年的 requests 後門、2024 年無數的 typosquatting 套件,手法大多是騙開發者安裝一次性的惡意包。但這一次完全不一樣。
攻擊者選擇了 lightning 這個套件 — 不是什麼冷門的套件,而是 PyTorch 生態系的骨幹之一。無論你是做影像分類、微調 LLM、跑 Stable Diffusion 還是開發時間序列模型,lighting 很可能就在你的 requirements.txt 裡。就在大家對 PyPI 的警戒心還停留在「不要亂裝來路不明的套件」時,攻擊者直接攻陷了一個你每天都在用的正牌套件。
當你執行 pip install lightning,一切看起來正常。版本號對、相依性正常、官網一致。但事實上,惡意套件在 _runtime/ 目錄下藏了一個混淆過的 JavaScript payload,一旦 Python import 觸發,它就開始運作。
跨生態系的擴散鏈:從 PyPI 燒到 npm
這才是這起事件最恐怖的地方。傳統的供應鏈攻擊止步於單一封裝生態系 — PyPI 的毒留在 PyPI,npm 的毒留在 npm。但 Shai-Hulud 打破了這個邊界。
惡意程式在受害機器上找到 npm publish 的憑證後,會執行以下操作:
- 在每個該 token 有權限發布的套件中注入
setup.mjs與router_runtime.js - 在
package.json中設定scripts.preinstall去執行植入的器 - 自動 bump patch 版本號並重新發布
- 任何下游開發者安裝了這些被汙染的 npm 套件,就會在自己的機器上啟動完整的惡意程式
一個 PyPI 套件被汙染,可以透過受害者的 npm 憑證,汙染整個 npm 生態系。 這是真正意義上的跨生態系供應鏈攻擊。
四通道資料竊取:一層被封還有三層
攻擊者設計了四條並行的資料通道,確保只要有一條能通,偷到的資料就出得去。
第一通道:HTTPS POST 到 C2 伺服器。 這是經典手法。偷到的資料立即透過 443 埠傳送到攻擊者控制的伺服器。C2 的域名和路徑以加密字串形式存在 payload 中,對靜態分析做了基本的反制。
第二通道:GitHub commit search 死信投放。 這招非常高明。惡意程式會用 commit message 前綴 EveryBoiWeBuildIsAWormyBoi 去輪詢 GitHub commit search API,尋找格式為 EveryBoiWeBuildIsAWormyBoi:<double-base64-encoded-token> 的 dead-drop 指令。解碼後的 token 用來認證 Octokit 客戶端,進行後續操作。這意味著攻擊者可以隨時透過 GitHub commits 下達指令,而流量看起來完全正常。
第三通道:建立公開 GitHub repo。 程式會建立一個隨機的沙丘風格的 repo 名稱,描述為「A Mini Shai-Hulud has Appeared」,然後把偷到的資料已 base64 編碼的 JSON 形式 commit 進去。超過 30MB 的檔案會被自動分段。commit message 一律使用無害的 chore: update dependencies。
第四通道:推送到受害者自己的 repo。 如果程式拿到 ghs_ 開頭的 GitHub server token,它會直接把資料推到受害者 repo 的所有 branch 上。你連 repo 都不用另外開,資料自己送上門。
它在偷什麼?比你想像的還要多
不像過去大部分惡意套件只偷環境變數或 SSH key,Shai-Hulud 的目標範圍幾乎涵蓋了一名 AI 工程師的所有數位身份:
本地檔案: 掃描超過 80 個憑證檔案路徑,尋找 ghp_、gho_ 和 npm_ 開頭的 token。
環境與 shell: 執行 gh auth token 抓取 GitHub CLI 憑證,並傾印所有環境變數。
GitHub Actions CI/CD: 針對 Linux runner,透過嵌入的 Python 腳本從 Runner.Worker 行程中傾印記憶體,提取所有標記為 isSecret:true 的 secrets,包括 GITHUB_REPOSITORY 和 GITHUB_WORKFLOW。
GitHub 組織: 檢查 token 的 scope(repo、workflow)後,遍歷組織層級的 GitHub Actions secrets。
AWS: 嘗試環境變數、~/.aws/credentials 設定檔、IMDSv2(169.254.169.254)和 ECS(169.254.170.2)來獲取憑證,接著呼叫 sts:GetCallerIdentity 確認身份,然後列舉並提取所有 Secrets Manager 值和 SSM 參數。
Azure: 使用 DefaultAzureCredential 來列舉訂閱和存取 Key Vault secrets。
GCP: 透過 GoogleAuth 認證後,列舉並提取所有 Secret Manager secrets。
換句話說,任何在受影響視窗內匯入了惡意套件的機器,所有雲端服務商的憑證都已經暴露了。
開發者工具變成後門:Claude Code 和 VS Code 都被利用了
這是這起事件中最值得關注的技術細節。Shai-Hulud 被認為是首個實際利用 Claude Code hook 系統的惡意軟體。
針對 Claude Code: 惡意程式會在感染的 repo 中寫入 .claude/settings.json,設置一個 SessionStart hook,matcher: "*",指向 node .vscode/setup.mjs。這表示每次開發者在該 repo 中啟動 Claude Code 時,不需要任何 tool use 或使用者操作,惡意程式就會自動執行。
針對 VS Code: 同樣的手法透過 .vscode/tasks.json 實現,使用 runOn: folderOpen 設定,只要打開專案資料夾就會觸發。
兩個 hook 都指向同一個 dropper — setup.mjs。這是一個自包含的 Bun runtime 引導程式。如果系統上沒有安裝 Bun,它會自動從 GitHub Releases 下載 bun-v1.3.13,支援 Linux x64/arm64/musl、macOS x64/arm64 和 Windows x64/arm64。然後執行完整的 14.8MB payload(router_runtime.js),最後清理 /tmp 中的暫存檔案,不留痕跡。
Bonus:惡意 GitHub Actions workflow。 如果惡意程式持有具 write 權限的 GitHub token,它還會在受害者的 repo 中推送一個名為 Formatter 的 workflow。這個 workflow 會在每次推入時,透過 ${{ toJSON(secrets) }} 傾印所有 repo secrets 並上傳為可下載的 Actions artifact。動作被 pin 到特定的 commit SHA 以顯得正當。
影響評估:不只是安全團隊的責任
對於使用 PyTorch Lightning 的團隊來說,這起事件的影響範圍取決於你的部署方式:
場景一:本地開發環境 — 如果你在本機 pip install lightning==2.6.2 或 2.6.3,你的個人 GitHub token、SSH key、雲端 SDK 憑證都已經暴露。需要假設所有環境變數和 CLI 憑證都已外洩。
場景二:CI/CD 流水線 — 如果 CI runner 安裝了受影響版本,GitHub Actions secrets、AWS/Azure/GCP 的 CI role 憑證全部受損。CI token 通常具有高特權限,可能導致跨 repo 的汙染。
場景三:容器映像 — 如果你的 Docker image 基於某個時間點鎖定了 lightning==2.6.2 並被 push 到 registry,任何 pull 該映像並執行的環境都在風險中。
根據 Semgrep 的建議,以下是具體的應對步驟:
第一步:確認是否受影響
– 檢查你的依賴中是否有 lightning==2.6.2 或 lightning==2.6.3
– 查看 pip freeze 或 poetry.lock / requirements.txt
– 如果你使用 Semgrep,可以直接在 advisories 頁面確認
第二步:隔離與清除
– 若有受影響的環境,立即隔離該機器,不要只刪除套件
– 假設該環境中的所有憑證都已外洩
– 旋轉所有可能暴露的 token:GitHub token(ghp_/gho_)、npm token、雲端憑證
– 尤其注意 GitHub Actions 的環境 secrets — 它們可能被傾印
第三步:審查可疑檔案
在 repo 中檢查以下檔案是否存在:
– .claude/settings.json(特別是含有 SessionStart hook 的設定)
– .claude/router_runtime.js
– .claude/setup.mjs
– .vscode/tasks.json(特別是含有 runOn: folderOpen 的任務)
– .vscode/setup.mjs
– _runtime/start.py(在安裝目錄中)
– .github/workflows/ 下的意外 workflow(特別是名為 Formatter 的)
第四步:監控 GitHub
– 搜尋你的組織中是否有描述為「A Mini Shai-Hulud has Appeared」的 repo
– 檢查是否有 commit message 前綴為 EveryBoiWeBuildIsAWormyBoi 的異常提交
– 檢查 GitHub Actions 的 workflow run 記錄中是否有異常的 artifact 上傳
比起技術漏洞,這是生態系的結構性問題
平心而論,這次攻擊沒有用到任何零日漏洞。沒有 kernel exploit,沒有協議漏洞,完全靠的是生態系本身的設計特徵。
PyPI 的套件審核機制遠不如 npm 完善,而 npm 的預安裝腳本機制又讓攻擊者有機可乘。但 Shai-Hulud 的高明之處在於,它同時利用了這兩個生態系的缺陷,還跨過邊界把兩者串在一起。
更令人擔憂的是開發者工具層面的攻擊面。Claude Code 的 hook 系統設計用意良善 — 讓開發者可以自訂 AI 助理在專案中的行為。但它沒有驗證 hook 檔案的來源或簽章,導致只要惡意程式能寫入 .claude/settings.json,就能在使用者不知情的情況下控制每個 AI 對話。VS Code 的 tasks.json 有類似的問題。
這不是要怪 Claude Code 或 VS Code。這是一種新類別的攻擊面 — 開發者工具本身的擴展機制正在成為供應鏈攻擊的理想載體。在 AI 輔助開發工具快速普及的當下,這個問題只會越來越嚴重。
或許這起事件最重要的教訓是:在 AI 供應鏈安全中,沒有任何「常用套件」是安全的,沒有任何「開發者工具」是免疫的。當你下一次執行 pip install 或 npm install 時,記住一個 14.8MB 的 JavaScript 檔案正在一千公里外的機房裡等著你的 token。不是嚇人,這是 2026 年 4 月 30 日真實發生的故事。