首页 › programming › 一个PR如何劫持整个NPM生态

一个PR如何劫持整个NPM生态:Mini Shai-Hulud供应链攻击全解析

2026年5月11日,北京时间凌晨3点20分,一个名叫TeamPCP的黑客组织用6分钟时间向npm注册表投毒84个包,波及TanStack、OpenSearch、Mistral AI、UiPath等170多个知名项目。这不是又一起"开发者密码泄露"的老套路——攻击者靠的是一个Pull Request,就撬开了整个npm供应链的信任锁链。Fireship频道在3天后发布的视频"A single PR just hijacked the NPM registry...",用不到7分钟把这个事件讲得清清楚楚。4.2M订阅的开发者顶流频道、极其时效性的话题、直接关乎每一位Node.js开发者的日常工作——这就是本期深度解读的视频。

视频背景卡片

项目 内容
视频标题 A single PR just hijacked the NPM registry...
频道 Fireship
时长 约7分钟
播放量 发布数日内迅速攀升(Fireship频道总播放超7亿)
发布日期 2026年5月14日
核心主题 Mini Shai-Hulud npm供应链蠕虫攻击的技术拆解

核心内容拆解

1. 六分钟的精确打击:时间线还原

Fireship在视频开篇就点明了这次攻击的震撼之处——仅用6分钟,从19:20到19:26 UTC,攻击者在42个@tanstack包中发布了84个恶意版本。但TanStack只是冰山一角。根据Aikido、Snyk、Akamai等多家安全公司的后续调查,实际波及范围包括:

总计170+个包被感染。这不是一个手工操作的攻击者能完成的——这是一条自动化蠕虫。Fireship在视频中强调了攻击的速度和规模,这也是Mini Shai-Hulud名称的由来:比2025年9月的原始Shai-Hulud更"mini"(轻量)、更快、更自动化。

延伸分析:5个月内的第5波攻击,每一波都在扩大攻击面。原始Shai-Hulud影响了526个库,而Mini版本虽然单次规模更小,但传播效率更高,攻击间隔更短。这说明TeamPCP在持续迭代其攻击工具链。

2. 攻击机制:一个PR如何变成核弹

这是整个事件最令人细思极恐的部分。Fireship在视频中用标志性的高密度讲解风格,拆解了攻击链:

Step 1:投毒CI/CD缓存。 攻击者向目标仓库提交一个看似正常的Pull Request。这个PR本身不包含任何恶意代码——它只是触发了CI/CD流水线。

Step 2:利用npm生命周期脚本。 当CI/CD流水线运行npm install或npm publish时,恶意payload通过preinstall、postinstall等lifecycle scripts被激活。这是npm设计中一个长期被诟病的安全隐患。

Step 3:窃取发布凭证。 恶意脚本从CI环境变量中提取npm publish token,或者直接利用GitHub Trusted Publishing的OIDC token。

Step 4:自动发布恶意版本。 蠕虫用窃取的凭证,自动向npm注册表发布被感染的包版本。

Step 5:自我传播。 被感染的包在下游用户安装时再次执行lifecycle scripts,如果受害者也是npm包维护者且CI/CD配置不当,蠕虫就会跳到下一个组织,继续传播。

flowchart TD
    A[攻击者提交恶意PR] --> B[目标仓库CI/CD被触发]
    B --> C[npm install 执行 postinstall 脚本]
    C --> D[恶意脚本窃取 CI/CD 凭证]
    D --> E[利用 Bun 运行时加载远端 payload]
    E --> F[自动发布 84 个被感染包版本]
    F --> G[下游开发者 npm install 被感染包]
    G --> H{受害者也是包维护者?}
    H -->|是| I[蠕虫跳转到新组织]
    I --> B
    H -->|否| J[窃取本地环境变量和密钥]

    style A fill:#e74c3c,color:#fff
    style F fill:#e74c3c,color:#fff
    style J fill:#f39c12,color:#fff

延伸分析:这次攻击的一个关键技术细节是使用了Bun运行时而非Node.js来执行恶意payload。Phoenix Security的分析指出,Bun的引入可能是为了绕过一些基于Node.js行为特征的安全检测工具。同时,利用GitHub Trusted Publishing的OIDC机制是一个极具讽刺意味的攻击向量——这个机制本来是为了提高发布安全性而设计的,却被攻击者反向利用了。

3. 为什么TanStack成为首选目标

Fireship在视频中专门提到TanStack并非随机选择。原因很明确:

延伸分析:这揭示了一个令人不安的悖论——开源项目越是做得好(自动化CI/CD、积极响应PR、Trusted Publishing),反而越容易成为目标。这不是TanStack的错,而是整个npm生态信任架构的根本性缺陷。

4. 微软、Snyk、Akamai的联合响应

攻击发生后,安全社区的响应速度相当快:

延伸分析:Microsoft的报告揭示了一个更深层的威胁——这些被窃取的CI/CD凭证如果落入攻击者手中,可能被用来进一步攻击依赖这些凭证的云基础设施。供应链攻击的影响绝不限于"npm包被污染"这么简单,它可能成为企业云环境全面沦陷的入口。

5. Shai-Hulud的前世今生:五波攻击的进化史

Fireship的视频聚焦于最新一波攻击,但理解完整背景才能看清趋势:

波次 时间 规模 关键特征
第1波 2025年9月 526个包 原始Shai-Hulud,首次展示npm蠕虫概念
第2波 2025年11月 ~200个包 改进传播机制,引入CI cache poisoning
第3波 2026年1月 ~180个包 针对axios等超级包的定向攻击(RAT植入)
第4波 2026年4月 ~160个包 Mini版本首次出现,引入Bun运行时
第5波 2026年5月 170+个包 本波攻击,TanStack+OpenSearch+Mistral AI

延伸分析:每一波攻击的核心改进方向是"更快、更轻、更自动化"。从第1波需要手动部分操作,到第5波完全自动化的6分钟投毒。攻击者的迭代速度令人担忧——他们的"DevOps"水平不亚于一流的开发团队。

6. npm生命周期脚本:一个"设计缺陷"还是"必要之恶"

这是整个事件的核心技术争议点。npm的postinstall、preinstall脚本机制允许包在安装时自动执行任意代码。这个功能有其正当用途(比如编译native模块),但它同时也是:

Fireship在视频中暗示npm应该默认禁用lifecycle scripts,但这引发了另一个问题——大量现有的构建工具链依赖这个功能。Node.js社区围绕--ignore-scripts flag的争论已经持续多年。

延伸分析:Deno和Bun在这方面做了一些改进——Deno默认不允许包执行任意脚本,Bun虽然在本次攻击中被攻击者利用,但其包管理器也提供了更细粒度的权限控制。但这些改进对于npm已有的数百万个项目来说,已经太迟了。

7. GitHub Trusted Publishing的信任悖论

Trusted Publishing是npm和PyPI近年来推出的安全功能,通过OIDC(OpenID Connect)token实现CI/CD环境的无密钥发布。理论上,这比维护者手动管理npm token更安全——token不会被泄露,因为它只在CI环境中短期存在。

但TeamPCP的攻击揭示了这个设计的一个致命盲区:如果CI环境本身被污染(通过恶意PR触发),那从"受信任的CI环境"中生成的OIDC token自然也是不可信的。

这就像一个银行金库的安保系统——密码没有泄露,但进入金库的人本身就是伪装的。

知识结构图

mindmap
  root((Mini Shai-Hulud\nnpm供应链攻击))
    攻击技术
      CI/CD缓存投毒
      npm生命周期脚本利用
      Bun运行时加载payload
      GitHub OIDC Token窃取
      自动化蠕虫传播
    受影响生态
      TanStack(42个包)
      OpenSearch
      Mistral AI SDK
      UiPath
      antv(蚂蚁集团)
    防御措施
      npm --ignore-scripts
      锁定依赖版本(lockfile)
      CI/CD环境变量最小化
      发布冷却期机制
      自动化安全扫描
    深层问题
      npm信任模型缺陷
      间接依赖不可控
      Trusted Publishing悖论
      开源维护者安全意识

实战启示

如果你是一名前端/Node.js开发者

  1. 立即检查你的依赖:运行npm audit和npx npm-check,确认没有安装被感染的版本号(参考Snyk和npm官方公告中的具体版本列表)。如果你的package-lock.json中包含2026年5月11-12日发布的@tanstack版本,立即回退到此前版本。

  2. 在项目中启用--ignore-scripts:在你的.npmrc中加入ignore-scripts=true,这样npm install时不会自动执行任何lifecycle scripts。如果你确实需要某些包的脚本(如native模块编译),使用npm rebuild手动触发。

  3. 审查你的CI/CD配置:检查你的GitHub Actions workflow是否在PR触发时执行了npm install或npm publish。如果PR触发的workflow中有publish步骤,立即改为仅main branch触发。

  4. 使用lockfile并验证完整性:永远不要运行npm update而不检查变更内容。package-lock.json是你对抗供应链攻击的第一道防线。

  5. 最小化CI环境变量权限:不要在CI环境中存储不必要的token。如果某个workflow不需要发布权限,就不要给它。

如果你是开源维护者

延伸学习路径

  1. Snyk原始分析:TanStack npm Packages Hit by Mini Shai-Hulud — 最及时的技术细节
  2. Akamai深度研究:Mini Shai-Hulud: The Worm Returns and Goes Public — CI cache poisoning机制详解
  3. Microsoft安全博客:Compromised @antv npm packages enable CI/CD credential theft — 最新一波的影响范围
  4. Phoenix Security全谱分析:TeamPCP's Self-Propagating npm Worm — 170个包的完整受影响列表
  5. Fireship频道:@Fireship on YouTube — 持续关注最新的开发者安全动态

一句话总结

一个PR触发CI/CD → 生命周期脚本窃取凭证 → 6分钟投毒170+个包 → 自我传播到更多组织——这不是科幻,这是2026年npm供应链的残酷现实,它迫使每一位开发者重新审视"我到底信任了谁"。

参考来源

  1. A single PR just hijacked the NPM registry... - Fireship — 分析的核心视频
  2. TanStack npm Packages Hit by Mini Shai-Hulud - Snyk — 首发技术分析
  3. Mini Shai-Hulud: The Worm Returns and Goes Public - Akamai — CI缓存投毒机制
  4. Compromised @antv npm packages - Microsoft Security Blog — 最新影响范围扩展
  5. TeamPCP's Self-Propagating npm Worm - Phoenix Security — 170个包完整分析

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入