Mini Shai-Hulud: Anatomy of a Massive npm Supply Chain Attack

The npm 生態系統再次成為大規模供應鏈攻擊的受害者。在 2026 年 5 月 19 日,npm 帳號 atool 被盜用,導致在短短 22 分鐘內,於 317 個不同的套件中自動發布了 637 個惡意版本。

這並非隨機的破壞行為,而是一場使用 "Mini Shai-Hulud" 工具包的高度協調行動——該框架與三週前發生的一起高知名度 SAP 攻擊事件使用了相同的框架。

這場攻擊針對高流量套件,包括 size-sensor (4.2M 月下載量) 和 echarts-for-react (3.8M),利用 semver 範圍內建的信任機制來自動感染下游專案。

The Execution Vector: Preinstall Hooks and Imposter Commits

攻擊者利用了兩條主要路徑來確保惡意載荷在受害者的機器上執行:

  1. Preinstall Hooks: 每個受害版本都新增了 preinstall 腳本 (bun run index.js)。由於這些腳本在依賴項完全安裝之前就會執行,因此惡意軟體會在執行 npm install 時立即獲得執行權限。
  2. Imposter Commits: 在一個複雜的操作中,有 630 個版本注入了指向 antvis/G2 GitHub 儲存庫的 optionalDependencies 項目。攻擊者向該儲存庫的分叉 (fork) 版本推送了具有偽造作者身份的 "orphan commits"。由於 GitHub 在分叉與父儲存庫之間共享對象存儲,npm 的 github: 解析機制會透過 SHA 抓取這些惡意提交,從而繞過分支保護與可見性。

Deep Dive: The Malicious Payload

惡意載荷是一個 498KB 的混淆 Bun 腳本,旨在進行全面的憑證竊取與系統持久化。

Comprehensive Credential Harvesting

惡意軟體採用掃描器架構,尋找超過 80 種環境變數,並使用正則表達式模式來抓取文件中的:

  • Cloud Keys: AWS (包括 EC2 IMDSv2 和 ECS metadata)、GCP 服務帳號以及 Azure 憑證。
  • Developer Tokens: GitHub PATs、npm tokens 以及 SSH keys。
  • Infrastructure Secrets: Kubernetes 服務帳號 token 與 HashiCorp Vault tokens。
  • Application Keys: Stripe keys、Slack tokens 以及資料庫連接字串。

Cloud and Container Escape

該工具包不僅限於環境變數。它會主動探測 AWS 憑證鏈,並嘗試透過檢查 Docker socket 來逃逸 Docker 容器。如果發現,它會嘗試啟動一個具有主機綁定掛載 (host bind mounts) 的特權容器,從來授予攻擊者對主機檔案系統的完整存取權。

CI/CD and Sigstore Abuse

在 CI 環境 (GitHub Actions, Jenkins, 等) 中,惡意載荷會執行一種特殊的攻擊:它將 GitHub Actions OIDC tokens 轉換為 npm publish tokens。這使得攻擊者可以利用流水線自身的身份來發布新套件。此外,它還使用 Sigstore (Fulcio 和 Rekor) 來簽署產物 (artifacts),建立具有偽造來源證明 (provenance) 的合法簽署二進位檔,使得這種攻擊在標準驗證工具面前幾乎是不可見的。

Persistence and the "Dead-Drop" C2

Mini Shai-Hulud 工具包旨在實現長期存取,採用了五種不同的持久化機制:

AI Agent Hijacking

惡意軟體特別針對現代 AI 編碼工具。它將 SessionStart hooks 注入到 .claude/settings.json (針對 Claude Code) 和 .vscode/tasks.json (針對 Codex/VS Code)。每當開發者啟動 AI 會話或開啟專案資料夾時,Bun bootstrapper 就會重新執行惡意載荷。

GitHub as a C2 Channel

惡意軟體並非與可疑的外部伺服器通訊,而是使用 GitHub API 作為其指令與控制 (C2) 通道。

  • Exfiltration: 竊取的數據被作為 Git objects 提交到在被盜 token 帳號下建立的公開儲存庫中。這些儲存庫遵循 Dune-themed 命名模式 (例如 fremen-sandworm-315)。
  • Remote Command Execution: 一個持久化守護程序 (kitty-monitor) 會輪詢 GitHub Search API 以尋找包含關鍵字 firedalazer 的提交。如果它發現了具有有效 RSA-PSS 簽名之提交,它會下載並執行連結的 Python 代碼。

CI/CD Workflow Injection

惡意載荷會將名為 "Run Copilot" 的惡意工作流注入到可訪問的儲存庫中。此工作流會將所有儲存庫 secrets 轉儲為 JSON artifact,攻擊者隨後會下載並刪在以抹除其蹤跡。

Community Reaction and Mitigation

這次攻擊的規模在開發者社群對於 npm 生態系統的安全性進行了重大辯論。許多用戶對持續依賴 preinstall 腳本表示沮喪,因為這提供了執行任意代碼的內建機制。

"NPM really desperately needs an 'allowBuilds' style allowlist... lifecycle script should be disabled by default in NPM." — @jonkoops / @tomxor

其他開發者建議採取更激進的措施,例如遷移至無根 (rootless) VM 引擎 (Podman) 或完全進行依賴項供應 (vendoring) 以避免上游更新。

How to Protect Your Projects

如果你懷疑你的環境已被入侵,請立即採取以下步驟:

  • Audit Lockfiles: 檢查 package-lock.json 是否有任何在 2026-05-19 發布的受影響套件版本。

  • Rotate All Secrets: 假設所有 AWS keys、GitHub tokens 以及對你的構建環境可存取的資料庫密碼皆已遭入侵。

  • Clean Local Environments: 搜尋 .claude/settings.json hooks、.vscode/tasks.json 自動執行任務,以及 kitty-monitor systemd 服務/LaunchAgent。

  • Implement Cooldowns: 使用如 npm config set min-release-age=2 的設定來防止自動安裝在過去幾天內發布的版本。

  • Use Install Proxies: 使用如 pmg (Package Manager Guard) 等工具,可以在腳本執行前對套件進行威脅情資蒐集評估。

Sources