ChainDrop:400+ npm 包遭自傳播蠕蟲感染,CI/CD 憑證成攻擊跳板

前言

2026 年 8 月 4 日,Microsoft Threat Intelligence 披露了一起代號爲 ChainDrop 的大規模 npm 供應鏈攻擊。攻擊者在數小時內向 npm 註冊表發佈了 440 餘個包、2200 多個惡意版本,波及 keyvflat-cachecache-manager 等高頻依賴,累計周下載量超過 5 億次。這不是一次簡單的包投毒——蠕蟲通過 preinstall 生命週期鉤子在 npm install 階段自動執行,竊取 npm、GitHub、AWS、Kubernetes、HashiCorp Vault 等憑證,再利用被盜身份自動修改並重新發布更多包,形成自我傳播的感染鏈。部分變種還會向倉庫注入 Claude 與 VS Code 配置文件,建立持久化後門。

本文基於 Microsoft、StepSecurity、SecurityWeek 等公開分析報告,梳理 ChainDrop 的攻擊鏈路、技術特徵與可操作的防護建議。

事件概覽:從 11 個種子包到 400+ 感染

ChainDrop 屬於 Mini Shai-Hulud 蠕蟲家族的演進版本,是 2025 年以來 npm 供應鏈攻擊浪潮中的最新一輪。與此前 Shai-Hulud 攻擊類似,但引入了 EtherHiding(以太坊區塊鏈 C2)等新技術。

時間線(UTC,2026-08-04):

  1. 攻擊者首先入侵 keyvcacheable 等命名空間維護者 Jared Wray 的 GitHub 賬戶。
  2. 09:00 UTCkeyv@6.0.0 等 11 個「種子包」被髮布,攜帶完整蠕蟲載荷。
  3. 惡意包在開發者工作站與 CI/CD _runner 上執行後,竊取憑證並自動向 npm 重新發布被感染包。
  4. 四小時內,StepSecurity 觀測到 444 個包、2212 個版本 被投毒;npm 團隊在約兩小時內開始下架惡意版本,但蠕蟲仍可通過新被盜賬戶持續傳播。

受影響範圍:

指標 數據
感染包數量 440+(StepSecurity 統計 444)
惡意版本數 2200+(StepSecurity 統計 2212)
種子包 11 個(keyv、cacheable 生態)
蠕蟲自動傳播 433 個額外包
周下載量 超 5 億次(SecurityWeek)

典型高危包包括 keyv@6.0.0(周下載約 1.5 億)、flat-cache@6.1.24(約 1.5 億)、file-entry-cache@11.1.6(約 1.47 億)——它們廣泛出現在 ESLint、cache-manager 等工具鏈中,意味着大量 JavaScript 項目可能間接依賴了被感染版本。

攻擊鏈路:preinstall 鉤子如何成爲入口

Microsoft 的分析指出,許多惡意版本 沒有對應的 GitHub 提交、PR 或 Tag,說明攻擊者並非逐個入侵源碼倉庫,而是直接修改 tarball 並通過被盜 npm 發佈令牌重新上傳。這是 ChainDrop 傳播速度極快的根本原因之一。

1. 入口:preinstall 生命週期鉤子

npm 在安裝依賴時會按順序執行生命週期腳本。ChainDrop 在被感染包的 package.json 中加入 preinstall 鉤子,指向包內的 setup.mjs

{
  "scripts": {
    "preinstall": "node setup.mjs"
  }
}

由於 preinstall 在包安裝完成 之前 就會運行,惡意代碼可以在單元測試、SAST 掃描等常規安全檢查啓動前就完成執行——無論是本地 npm install,還是 CI 流水線中的依賴安裝步驟,都可能觸發。

2. 二階段載荷:Bun 運行時 + 混淆腳本

setup.mjs 會下載合法的 Bun JavaScript 運行時,並加載約 710 KB 的混淆二階段腳本(常見文件名爲 Math_Symbol.jsmath_init.js)。使用 Bun 而非 Node.js 本身,有助於繞過部分針對 Node 進程的監控規則。

Microsoft Defender 已將該行爲標記爲 Suspicious usage of Bun runtimeTrojan:NPM/MalBun.A 等檢測項。

3. 憑證收集:從本地文件到雲 API

載荷啓動後會區分 開發者工作站CI/CD 環境

  • 在開發者機器上,進程會 detach 到後臺 繼續運行;
  • 在 CI 環境中,進程保持附着,以便讀取 workflow secrets、runner 憑證及 GitHub Actions OIDC 發佈權限。

收集範圍包括:

  1. 本地憑證文件、Shell 歷史、SSH 密鑰、雲配置文件;
  2. 進程環境變量(含 NPM_TOKENGITHUB_TOKEN 等);
  3. 通過 gh auth tokengcloudaz 等 CLI 獲取的令牌;
  4. 利用已獲憑證調用 AWS、Kubernetes、HashiCorp Vault API,枚舉並拉取更多密鑰。

4. 數據外傳:HTTPS + GitHub 備用通道

竊取的數據經 JSON 序列化、gzip 壓縮後,用 AES-256-GCM 加密,密鑰再用攻擊者 RSA 公鑰封裝。外傳路徑:

  1. 主通道:攻擊者控制的動態 HTTPS 端點。C2 域名通過以太坊智能合約(0xE1f2395ee43e45A1556EC6438a88c31B83493103)或簽名 GitHub commit(標記 thebeautifulmarchoftime)下發,分析時活躍域名爲 npm-cache.com,歷史候選包括 pypi-get.comjs-mirror.com
  2. 備用通道:利用被盜 GitHub 令牌創建公開倉庫,描述爲 「Shai-Hulud: Here We Go Again」,將加密結果以 results-*.json 文件提交。

5. 蠕蟲傳播:一個令牌感染所有可發佈包

ChainDrop 最具破壞力的能力在於 自動化傳播。獲得 npm 發佈令牌後,蠕蟲會:

  1. 枚舉該身份可訪問的所有包;
  2. 下載各包最新 tarball;
  3. 插入惡意 setup.mjsMath_Symbol.js,替換 lifecycle scripts;
  4. patch 版本號 +1 後重新發布。

一個被盜維護者賬戶即可在數小時內產出數百個惡意 patch 版本——且這些版本往往看起來只是普通的補丁升級,源碼倉庫卻毫無變動。

6. GitHub Actions OIDC 濫用

對於配置了 npm Trusted Publishing(OIDC)的倉庫,蠕蟲還有專門路徑:利用 workflow 身份獲取合法 provenance 的發佈權限,使惡意包攜帶 看似可信的來源簽名。這意味着僅靠 provenance 校驗不足以防禦此類攻擊。

7. 持久化:Claude / VS Code 配置注入

蠕蟲還會利用被盜 GitHub 憑證,向可寫倉庫分支注入配置文件:

  • .claude/settings.json.claude/setup.mjs
  • .vscode/tasks.json.vscode/setup.mjs

當開發者後續使用 Claude Code、VS Code 或 GitHub Copilot 打開項目時,載荷可能再次被觸發,形成 開發者到開發者 的二次感染路徑。部分 macOS/Linux 變種還安裝了「死手開關」:每 60 秒輪詢 GitHub API 檢測令牌有效性,令牌被撤銷則自毀;另有 24 小時自清理機制。

與 Shai-Hulud 的演進關係

ChainDrop 被安全社區視爲 Shai-Hulud 2.0 蠕蟲的重度演進版本,主要新增能力包括:

特性 Shai-Hulud(早期) ChainDrop
執行入口 postinstall / preinstall preinstall + Bun 二階段
C2 通信 靜態域名 / GitHub EtherHiding(以太坊合約動態下發)
傳播方式 手動或半自動 全自動 tarball 修改 + 重發布
持久化 有限 Claude / VS Code 配置注入
CI 目標 憑證竊取 憑證竊取 + OIDC 發佈濫用

蠕蟲還會檢測 俄語系統環境 並主動退出,這一特徵在 Microsoft 與 StepSecurity 的分析中均有提及。

如何自查:你的項目是否受影響

1. 檢查 lockfile 與 node_modules

對照 StepSecurity、Wiz、Socket 等廠商維護的 受影響包列表,檢索 package-lock.jsonyarn.lockpnpm-lock.yaml 中的版本號。不要只看直接依賴——被感染包多爲 傳遞依賴

# 示例:在 lockfile 中搜索已知高危包
grep -E '"(keyv|flat-cache|file-entry-cache|cache-manager)"' package-lock.json

2. 關注 IOC(入侵指標)

Microsoft 公佈的文件哈希:

SHA256 說明
54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668 setup.mjs(npm preinstall 加載器)
fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb setup.mjs(.claude / .vscode 加載器)
9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc Math_*.js 蠕蟲主體

網絡 IOC:npm-cache.compypi-get.comjs-mirror.com,以及 https://npm-cache.com:443/router

3. 檢查 CI 與本地環境

在終端或 SIEM 中檢索以下進程特徵:

# 可疑 preinstall 執行
node setup.mjs

# Bun 二階段加載(路徑含 bun-dl- 或 node_modules)
bun ... Math_Symbol.js

若發現匹配,應將該機器視爲 已失陷 處理。

應急響應與長期防護

若已安裝被感染版本

Microsoft 與 JFrog 的建議可歸納爲以下步驟:

  1. 隔離:斷開受影響工作站與 CI runner 的網絡,保留 tarball、npm 日誌、CI 日誌、GitHub audit log 以便界定暴露窗口。
  2. 清理:清除 node_modules、npm/yarn 緩存(含共享 CI 緩存);重建 runner 鏡像與 golden build 環境。
  3. 輪換憑證:在 已知乾淨的環境 中撤銷並輪換 npm token、GitHub PAT、AWS 密鑰、K8s ServiceAccount、Vault token 等——順序很重要,先隔離再輪換。
  4. 審計倉庫:檢查 .claude/.vscode/ 目錄是否有異常注入;審查 GitHub Actions workflow 變更與 npm 發佈記錄。
  5. 重建制品:從已知良好的依賴基線重新構建,確認緩存與製品庫中不存在被感染哈希。

日常防護建議

  1. 升級 npm CLI 至 v12+,啓用 min-release-age 功能,延遲安裝剛發佈的版本,爲社區下架爭取窗口。
  2. 鎖定依賴版本(pin / lockfile commit),避免 CI 中無鎖自動拉取最新 patch。
  3. CI 中禁用 lifecycle scripts 或使用 --ignore-scripts(需評估對原生模塊的影響):
npm ci --ignore-scripts
  1. OIDC Trusted Publishing 仍推薦使用,但需配合 workflow 審批、環境保護規則與異常發佈告警,不能作爲唯一防線。
  2. 最小權限原則:npm 發佈 token、GitHub PAT、雲 IAM 角色應限定到必要範圍;CI secrets 按 job 隔離。
  3. 供應鏈監控:接入 Socket、Snyk、Dependabot 等工具,對新增 patch 版本做 diff 與行爲分析。

寫在最後

ChainDrop 再次證明:npm 供應鏈的安全邊界早已超出「某個包有沒有被入侵」——CI/CD 憑證、OIDC 發佈鏈、AI 開發工具配置 都可能成爲攻擊跳板。一個維護者賬戶的 GitHub 泄露,可以在四小時內演變成波及數百個包、數億次周下載的蠕蟲風暴。

對普通開發者而言,當下最務實的動作是:覈對 lockfile、清理緩存、輪換可能暴露的令牌。對團隊而言,則需要把依賴安裝、發佈流程和憑證管理當作同一套安全體系來審視——因爲下一次攻擊,很可能還是從 npm install 的那一行 preinstall 腳本開始。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜