Total Pageviews

Sunday, 24 May 2026

你的npm包可能在偷你的密钥:一场惊心的攻击

 听说了嘛,有用户跑了个 npm install命令,结果GitHub 的令牌、AWS 的密钥、连SSH私钥都被偷走了?

这不是假设。2026年5月12日,安全机构 Socket 发出紧急警报——npm 生态遭遇了有史以来规模最大的供应链投毒事件之一:超过 160 个 npm/PyPI 包被植入恶意代码,包括前端圈耳熟能详的 TanStack(周下载量超 1200 万次)、Mistral AI 的官方 SDK、UiPath 企业自动化工具链,全部中招。

更离谱的是,这次攻击不需要偷任何人的密码。攻击者直接在 GitHub Actions 的内存里把 OIDC 令牌”读”了出来,然后用这个合法令牌把恶意包发布到了 npm——带着有效的 provenance 签名。
一场”技术上完美”的供应链攻击

这次攻击被安全圈称为 “Mini Shai-Hulud”,由威胁组织 TeamPCP 主导,攻击链设计得相当精密。

第一步,攻击者先分析了 TanStack 项目的 GitHub Actions 发布流程,找到了三个漏洞的组合利用路径:

    pull_request_target 缓存投毒:攻击者 fork 了 TanStack/router 仓库,提交了一个 PR,触发了带有 pull_request_target 的 CI 流程。这个流程会把攻击者控制的 pnpm 缓存产物注入到构建环境中。
    跨 fork 缓存污染:当真正的维护者合并 PR 并触发正式发布流程时,受污染的缓存被恢复,攻击者植入的恶意二进制文件随之执行。
    OIDC 令牌内存读取:恶意代码直接读取 GitHub Actions 运行器进程的内存(/proc/<pid>/mem),提取出 OIDC 令牌。

拿到 OIDC 令牌后,攻击者不需要任何账户密码,直接以 TanStack 官方的”受信任发布者”身份,把恶意版本推送到了 npm 注册表。

这就是最可怕的地方:这些恶意包携带了有效的 npm provenance 签名,意味着传统的”看签名判断包是否可信”这条路也被堵死了。
恶意代码做了什么?

被篡改的包在 package.json 中新增了一个 optionalDependencies 依赖项,指向一个伪造的包 @tanstack/setup,以及一个恶意的 prepare 生命周期钩子。

一旦你 npm install 了受影响版本的包,钩子自动运行,恶意代码会:

    扫描并窃取 AWS IMDSv2/GCP/Azure 的云凭据
    读取 Kubernetes 服务账户令牌、HashiCorp Vault 令牌
    翻找 ~/.npmrc、GitHub 个人访问令牌、SSH 私钥
    所有数据通过 Session 网络(去中心化加密通讯)+ typosquat 域名 + GitHub API dead drops 三条通道外传

更绝的是,恶意包还有蠕虫式的自我传播能力。如果受感染的机器上有 npm 发布权限,代码会自动修改那些有发布权限的包,把恶意依赖也一并注入进去,再利用窃取的令牌发布新版本——每个受害者的机器都变成了新的传播节点。

npm供应链攻击示意图
最狠的一手:删你没商量

你以为 revoke 令牌就完事了?图样图森破。

如果攻击者在你的机器上检测到一个有组织写权限的 GitHub 令牌,会自动安装一个持久化 daemon(macOS 用 LaunchAgent,Linux 用 systemd user service),这个 daemon 每 60 秒检查一次 GitHub——一旦发现令牌被吊销,直接执行 rm -rf ~,清空你的 home 目录。

安全公司的建议是:在吊销任何令牌之前,必须先找到并删除这个 daemon,否则删令牌反而会触发数据毁灭。

这个 daemon 在 macOS 上的路径是:~/Library/LaunchAgents/com.user.gh-token-monitor.plist。Linux 用户则检查 ~/.config/systemd/user/gh-token-monitor.service。
波及范围:比你想的大得多

事件披露后,波及范围迅速扩大。最初是 TanStack 旗下的 42 个包,但到当天结束,受影响命名空间已包括:

    @tanstack(83 个恶意版本)
    @uipath(66 个恶意版本)
    @mistralai(npm + PyPI 双端,官方 SDK 全军中招)
    @squawk(87 个恶意版本)
    @tallyui、@beproduct 等企业级包
    OpenSearch(npm 周下载 130 万次)

甚至安全工具 guardrails-ai(PyPI)的 0.10.1 版本也未能幸免。

总计:超过 160 个包名、373 个恶意版本,横跨 npm 和 PyPI 两大生态。
我们该怎么做?

如果你在5月份左右 npm install 过任何 TanStack 包,或者用企业 CI 跑过相关项目,现在立刻做这几件事:

第一步:检查是否有 persistence daemon(先做这个!)

# macOS
ls ~/Library/LaunchAgents/com.user.gh-token-monitor.plist

# Linux
ls ~/.config/systemd/user/gh-token-monitor.service

如果存在,先删掉,再吊销令牌。

第二步:轮换所有凭据

从受影响的机器上:GitHub PAT、npm token、AWS/GCP/Azure 密钥、Kubernetes SA token、SSH 私钥,全部轮换。

第三步:审计代码仓库

git log --all --author=claude@users.noreply.github.com

搜一下是否有来历不明的提交。同时检查 .claude/ 和 .vscode/ 目录里有没有 router_runtime.js 或 setup.mjs 这样的可疑文件——它们在 npm uninstall 后依然会存活。

第四步:检查 CI 配置

确保所有不需要 OIDC 发布的工作流都设置了 permissions: id-token: none,限制 GitHub Actions OIDC 令牌的作用域。

第五步:堵 C2 通道

在 DNS 或代理层阻断以下域名/IP:
– git-tanstack[.]com(typosquat)
– *.getsession.org(Session 网络)
– 83.142.209.194
这件事真正可怕的地方

回过头来看,这次攻击真正让人脊背发凉的不是技术有多高超,而是“可信”这个基础被动摇了。

你信任 GitHub Actions 的 OIDC 机制,它没问题。你信任 npm 的 provenance 签名,它也没问题。但攻击者把这两个”没问题”串起来,就绕过了一整套安全假设。

而且,攻击者甚至把 Shai-Hulud 的源代码短暂地发布到了 GitHub 上——在被删除之前已经被 mirror 到了其他地方。这意味着接下来会有大量的 copycat 攻击,用同样的手法去搞其他知名的开源项目。

开源生态的供应链安全,真的到了需要认真面对的时候了。我们享受着 npm install 带来的便利,却不得不承认:我们其实把太多信任交给了一个我们并不完全了解的生态系统。

你最近一次更新依赖是什么时候?有没有觉得哪个包加载得”稍微有点慢”?

参考资料:

  • Socket 官方警报
  • Snyk 深度分析
  • Orca Security 技术报告
  • SecurityWeek 报道
  • IT之家中文报道
  • No comments:

    Post a Comment