Skip to content

ChainDrop 自传播 npm 蠕虫事件:从包投毒到 CI 凭据扩散 ​

摘要 ​

2026 年 8 月,多家安全团队披露了针对 keyv、cacheable 等 npm 包的自传播活动(ChainDrop,也被报道为 Mini Shai-Hulud)。恶意版本在安装阶段执行代码,搜索开发者主机和 CI/CD 环境中的令牌、云凭据与发布凭据,再把受害者凭据用于修改更多包或继续传播。8 月 28 日,@7nohe/openapi-react-query-codegen 又出现同类恶意版本:攻击者利用任何用户均可触发的 GitHub Actions 评论发布路径,在持有 id-token: write 的真实工作流中取得 npm 受信发布凭据。由此生成的恶意包带有有效的 SLSA provenance,说明来源证明只能确认“由哪个工作流构建和发布”,不能证明该工作流处理的代码与触发者可信。不同来源对受影响包数量、样本细节和活动归因的统计口径不同;本文只合并机制一致且可由公开材料核对的事实。

攻击链的现实特征 ​

ChainDrop 把依赖生态中的多项已知风险串成了可验证的真实攻击链:“安装执行—凭据搜集—包发布/传播—冷却期规避”。其研究价值在于公开生态中实际发生的横向扩散,而不是实验室中的假设攻击。

威胁模型与攻击链 ​

  1. 攻击者取得或冒用热门包维护者的发布权限,上传带有安装钩子的版本。
  2. 下游项目正常安装或更新依赖,钩子在开发机、构建器或 CI Runner 上执行。
  3. 载荷枚举 .npmrc、云 CLI、GitHub Actions、AI 工具和常见加密钱包位置,收集可重放的令牌。
  4. 盗取的发布令牌被用于修改其他包、写入恶意版本或把数据放到公共 C2/区块链通道,形成自传播闭环。

OpenAPI React Query Codegen 样本补充了上游发布控制被绕过的具体路径。仓库原有 issue_comment 工作流只检查评论内容是否等于 npm publish,没有校验评论者与仓库的关系;作业随后检出 Pull Request 的 Head 并执行 pnpm install。攻击者因此可从自己的 Fork 提交带 preinstall 的代码,再通过评论让其在具有 id-token: write 权限的发布作业中运行,获取 npm 受信发布令牌并发布任意版本。仓库维护者确认 PR #215 和 #216 被用于该路径,并在事后删除评论触发器、撤销受信发布者和长期令牌,将发布入口收敛到标签推送。

这一路径还改变了对 provenance 的防护判断:十个恶意版本通过项目真实的 GitHub Actions 发布流程产生,其中的 SLSA provenance 在密码学和身份绑定层面仍然有效。失效点不是证明被伪造,而是工作流把未经授权的评论和 Fork 代码带入高权限发布作业;因此只验证 provenance 是否存在,不能替代对触发者授权、检出引用、构建输入和工作流权限的校验。

Pillar Security 对后续样本的分析补充了更早的执行入口:部分受污染仓库同时写入 Claude Code SessionStart Hook 和 VS Code folderOpen 任务,使代码审查者只需打开仓库或启动编码 Agent,就可能在第一次提示词和会话内策略生效前触发仓库内的加载器;npm preinstall 仍覆盖普通包消费者。该机制不依赖模型服从恶意提示,最先失效的是开发工具把仓库控制的生命周期配置当作可信本地设置。是否自动执行仍取决于工具版本、Workspace Trust、本地策略和确认流程,不能把“仓库含恶意配置”等同于所有克隆者均已执行。

GitGuardian 披露的后续波次(2026-08-07,同一 keyv/Mini Shai-Hulud 活动的延续,非独立事件)显示该载荷在功能上持续演进,感染机制(npm preinstall 钩子下载混淆 JavaScript 载荷)本身未变,但取值范围明显扩大:

  • 硬编码的凭据搜索位置从早期版本的 189 处扩大到 469 处,新增覆盖 AI 编码工具(Cursor、Gemini)凭据、更多 CI/CD 工具(ArgoCD、Jenkins)、加密钱包(Solana、Electrum)和云平台(Hetzner、阿里云)。
  • 搜索范围从仅当前用户主目录扩大到枚举系统上的全部用户,包括管理员账号。
  • 新增从以太坊区块链读取 C2 服务器地址的机制——GitGuardian 称这是 Mini Shai-Hulud 家族首次出现的技术,使 C2 基础设施更难被传统域名/IP 封禁式应对手段下线。

OpenAPI React Query Codegen 的十个恶意版本还展示了两条不同的安装执行路径。0.5.4、1.6.3、2.2.1 和 3.0.3 没有显式安装脚本,而是在 binding.gyp 的条件表达式中嵌入经 Unicode 转义的间接调用;npm 在检测到 binding.gyp 且不存在自定义 install 脚本时会默认运行 node-gyp rebuild,从而加载后续 JavaScript。另四个正式版本同时加入显式 preinstall;两个 0.0.0-* 预发布版本只有 preinstall,但因原项目的 files: ["dist"] 未把后续文件打入包中而不能按同一路径完成执行。检测若只查 preinstall 或只查 binding.gyp,都会漏掉一部分版本。

攻击方法与复现材料 ​

以下为依据维护者公告和 GitHub Security Advisory 重构的去武器化控制流,只用于验证工作流授权与安装期检测,不含原始载荷、外传端点或凭据处理代码:

text
不可信用户在 Fork PR 下评论 "npm publish"
  → release.yml 未校验 author_association
  → 检出 pull/<number>/head
  → pnpm install 执行 Fork 控制的安装钩子
  → 高权限作业仍具有 id-token: write
  → npm 受信发布流程签发短时发布凭据
  → 恶意版本获得有效 provenance 并进入注册表

防御性检查应同时覆盖三类信号:issue_comment 触发的发布作业是否校验评论者权限;高权限作业是否检出不可信 PR Head 并安装依赖;包内容是否出现异常 binding.gyp、随机命名的大体积 JavaScript 或新增安装钩子。不要运行可疑包;可在禁网、无凭据的隔离环境中仅解包并比较 package.json、binding.gyp 和文件清单。

证据与影响 ​

Unit 42、Microsoft、Elastic、Socket 和 GitGuardian 均报告了受污染包、安装阶段行为或凭据搜集路径;各报告对“受影响包数”(数百至 800+)和具体波次的划分不同,不能简单相加。公开证据足以确认供应链入侵和凭据暴露风险,但不能据此推断所有下载者均被成功入侵。

Socket 对 OpenAPI React Query Codegen 样本的分析把目标范围进一步具体化:载荷不只发现 npm、GitHub、SSH 和云平台凭据,还检查其他包注册表的认证信息以及 AI Agent/编码工具配置,意图利用可用凭据继续发布、访问代码仓库或维持开发环境中的执行入口。GitGuardian 记录的早期波次同样把 Cursor、Gemini 凭据纳入搜索目标,说明攻击者已将 AI 开发工具的本地凭据和配置视为与传统 CI/CD 令牌同等价值的资产。公开材料能证明样本包含这些发现与收集逻辑,但不能证明每一类凭据均已成功取得或被滥用;区块链托管 C2 地址也仍缺少独立复现。

维护者确认十个 OpenAPI React Query Codegen 恶意版本在 2026 年 8 月 28 日 20:00–20:21 UTC 发布,latest 曾短暂指向恶意的 3.0.4;npm 随后移除全部十个版本,latest 恢复为 3.0.2。版本删除阻止新的正常解析,但不会撤销已发生的安装,也不能排除缓存、镜像或既有构建产物中的残留。

防护与验证 ​

  • 对 npm 依赖启用锁文件、包完整性哈希和受信发布者/来源策略;新版本先在隔离构建器中执行安装脚本并记录网络行为。
  • 将 CI 发布令牌改为短时、仓库和环境绑定的 OIDC 凭据,禁止在普通构建步骤读取长期 NPM_TOKEN。
  • 对所有由评论、Issue、PR 或外部事件触发的发布工作流执行显式授权校验;不得在检出不可信 PR Head 后向同一作业授予 id-token: write,并将发布限定到受保护标签或环境审批。
  • 验证 provenance 时同时核对触发事件、工作流版本、检出的 Git 引用和授权主体;不能把“证明有效”等同于“构建内容可信”。
  • 扫描包内容时同时检查安装钩子和 binding.gyp 等原生构建入口,避免仅依据 package.json 中是否存在 preinstall 判断是否会执行代码。
  • 对 .npmrc、GitHub Actions Secret、云元数据和 Agent 配置文件建立文件访问与外传告警;发现命中后立即撤销并轮换,而不是只删除恶意包。
  • 监控包版本在冷却期结束、锁文件和缓存生成时的异常变化,并把发布身份、构建证明和审计日志关联起来。

局限与待验证问题 ​

这是多家厂商对相近时间段活动的公开分析,不是统一取证数据集。OpenAPI React Query Codegen 的恶意发布路径、受影响版本、有效 provenance 和上游处置已由仓库维护者及 GHSA 交叉确认;但 Socket 将其联系到 Mini Shai-Hulud 的家族归因、跨注册表凭据验证细节、AI Agent 配置的实际利用情况,以及是否由同一操作者控制,仍属于进行中的调查,当前不能视为已经完成的统一归因。

包数量、下载量、缓存残留和受害者范围仍可能随注册表、镜像与后续调查变化。本文不把“下载”当作“执行成功”,不把样本中的目标列表当作已完成窃取,也不把未披露的受害者当作不存在。Socket 原文是单一厂商技术披露,本站没有执行恶意样本或独立复现其凭据发现、外传和传播逻辑;文中的机制结论限于公开工作流、维护者事件记录、GHSA 和厂商样本分析能够共同支持的部分。

参考链接 ​