本文面向:用 npm(包括 pnpm 和 yarn)安装 JavaScript 依赖的开发者、在 VS Code 或其衍生编辑器中使用扩展的人、从 GitHub Actions 发布包的维护者,以及 GitHub Enterprise Server 管理员。本文依据 TanStack、Nx 和 GitHub 发布的事后报告和公告撰写,不涉及攻击手法。
开发者今天该做什么
在锁文件和 CI 日志中查找受影响的 TanStack 版本
受影响的是 Router/Start 的42个包、84个版本,包括 @tanstack/react-router、@tanstack/react-start、@tanstack/router-core 和 @tanstack/history(完整列表见 GitHub 公告 GHSA-g7cv-rxg3-hmpx)。TanStack 表示 Query、Table、Form、Virtual 及其他包不受影响。不仅要检查锁文件当前的内容,还要检查2026年5月11日前后的变更历史。恶意版本在几小时内就从 npm 上被移除了,所以在那段时间内的安装可能不会出现在今天的锁文件里。在 CI 中,查找5月11日 UTC 19:20 之后运行过安装的作业。
确认你是否装过 Nx Console v18.95.0
Nx 的事后报告说明了如何用 code --list-extensions --show-versions 查看已安装的版本(扩展 ID 中包含 angular-console)。只有 v18.95.0 受影响,它在5月18日 UTC 12:30 至13:09 之间可以获取。Nx 要求,在该时间段内装有 Nx Console 且开启了自动更新的人,无论最终哪个安装数字是准确的,都要把这台机器视为已被入侵。事后报告还列出了需要查找的文件和进程(入侵指标);如果你受影响,请逐项检查。
如果受影响,轮换从那台机器能访问到的所有凭据
TanStack 和 Nx 列出的对象相同:GitHub 令牌、npm 令牌、SSH 密钥、云凭据(AWS、GCP、Azure)、Kubernetes、Vault 令牌,以及任何 .env 文件的内容。Nx 还补充了机器上的工具在该时间段内可能签发的凭据(临时云凭据、GitHub CLI 令牌等),并建议在轮换后考虑彻底重装这台机器。关于吊销顺序和如何处理常驻恶意软件,参见防御 npm 供应链蠕虫中“怀疑已经感染时”一节。
如果你维护 npm 包,检查发布历史
据 TanStack 称,这段代码会查找受害者维护的其他包,并尝试用同样的注入方式重新发布它们。如果你向 npm 发布包,请检查自5月11日以来,你的包的版本历史中是否有你没有发布过的版本。
查清你电脑上的 GitHub 令牌存放在哪里
据 Nx 称,被盗的凭据是 GitHub CLI 令牌。在那个环境中,它存放在磁盘上的一个文件里,以该用户身份运行的任何进程都能读取,并在74秒内就被用来调用 GitHub API。运行 gh auth status 查看你的令牌存放在哪里;如果是普通文件,考虑把它移到操作系统的钥匙串,或者使用只在运行时注入凭据的密码管理器集成。事件发生后,Nx 的政策已不允许在开发者电脑上直接使用 GitHub CLI。关于缩短令牌有效期和缩小权限范围,参见防御 npm 供应链蠕虫。
验证你的发布时长设置确实生效
据 Nx 称,被入侵贡献者的项目在 .npmrc 中设置了 minimum-release-age=10080(7天),但项目固定使用的 pnpm 10.14 不支持这个设置,并静默忽略了它。pnpm 从 10.16 开始支持。恶意版本在被安装时只发布了77分钟,所以只要设置真正生效,就能拦住它。请检查 package.json 中 packageManager 字段固定的版本,并让 CI 验证它足够新。npm 的对应设置,参见防御 npm 供应链蠕虫。
GitHub Enterprise Server 管理员:轮换签名密钥
5月26日,GitHub 宣布正在轮换密钥,包括为 GitHub Enterprise Server 更新包签名的密钥。管理员必须轮换其实例中的 GPG 公钥;否则今后的升级会失败,并报错称该文件不是有效的 GHES 包。操作说明和辅助脚本的 SHA256 摘要见 GitHub 的文章。GitHub 还要求客户只从官方来源下载 GHES 更新,并做好在未来几个月内以更高频率应用安全更新的准备。GitHub Enterprise Cloud 的客户无需采取任何行动。
包的发布者应检查 CI 中的哪些地方
TanStack 和 Nx 的事后报告都具体说明了是哪些设置让这条链条得以贯通。下面把这些发现转化为你可以在自己的仓库中检查的设置和策略。
不要在 pull_request_target 下运行 fork 的代码
据 TanStack 称,一个检查打包体积的工作流运行在 pull_request_target 上,并在其中检出并构建了来自 fork 拉取请求的代码。pull_request_target 以基础仓库的权限运行,TanStack 指出,针对首次贡献者的审批关卡不适用于这个触发器。只把它用于永远不运行外部代码的任务,例如打标签和发评论。事件发生后,TanStack 从 CI 中移除了所有 pull_request_target 的使用。
不要在不可信的作业和发布作业之间共享缓存
据 TanStack 称,GitHub Actions 缓存按仓库共享:pull_request_target 的运行和推送到 main 的运行使用同一个范围。把工作流的 permissions: 设为只读,也不能阻止保存缓存。结果,发布工作流恢复了一个由运行过外部代码的作业写入的缓存。事件发生后,TanStack 在发布流水线中禁用了包缓存,并清除了所有缓存。在执行发布的工作流中不恢复缓存,是最简单的一条界线。
只把发布权限(id-token: write)交给发布作业,并设置审批
TanStack 的发布工作流为 npm 可信发布(OIDC)持有 id-token: write。根据事后报告,恶意发布并不是来自工作流中定义的发布步骤;而是在同一次运行的另一个阶段中运行的代码提取了令牌并直接发布。TanStack 自己总结的教训是:可信发布者的绑定没有针对每次发布的审查。把发布拆成独立的作业,与构建和测试分开,只给这个作业权限,并放在设置了必需审阅者(required reviewers)的 GitHub 环境之后。事件发生后,Nx 规定发布必须经过触发运行者以外的人批准。
把第三方 Action 固定到提交 SHA
事件发生后,TanStack 和 Nx 都把所有 Action 引用固定到了提交 SHA,而不是标签或分支。TanStack 把可移动的引用称为“与这次事件无关、一直存在的供应链风险”。
把发布通知和审计日志交给会去看的人
Nx 是通过扩展市场在每次上传时发送的常规通知邮件发现被篡改的版本的。一位并没有预期会有新版本的维护者意识到这是异常,在大约11分钟内撤下了它。第二个分发渠道没有这样的通知,在那里撤下花了大约36分钟。与此同时,用被盗令牌进行的活动(例如删除工作流运行记录)在审计日志中放了一周都无人察觉。请确认发布通知能送达团队中的某个人,并且有人盯着审计日志中被删除的工作流运行记录。
发生了什么(依据三家组织的公开说明)
以下内容均依据 TanStack 的事后报告、Nx 的事后报告和 GitHub 的公告。时间为 UTC。
2026年5月11日 19:20–19:26
通过 TanStack 的 Router/Start 仓库的发布工作流,42个包的84个恶意版本被发布到 npm。5月11日 19:46
一名外部研究人员在 TanStack 的仓库中提交了详细报告。TanStack 开始应对。5月11日 20:43
一名 Nx 贡献者在一个与 Nx 无关的项目中运行pnpm install,解析到了恶意的@tanstack/zod-adapter@1.166.15。据 Nx 称,GitHub CLI 令牌被盗,并在74秒内被使用。5月11日 21:03 之前
TanStack 已将全部84个版本标记为弃用(deprecated)。5月11日 22:13–23:55
npm 从注册表中移除受影响的 tarball。5月15日
TanStack 宣布解除警报:目前发布的所有版本都是安全的。5月18日 12:30–13:09
利用被盗的贡献者权限,Nx Console v18.95.0 被发布到两个扩展分发渠道,随后被撤下。5月18日(周一,美国时间)
GitHub 检测并控制了一起涉及被投毒 VS Code 扩展的员工设备入侵,移除了恶意扩展版本并隔离了该终端。关键密钥在当天和次日完成轮换。5月20日
GitHub 公开此事:其评估是只有 GitHub 内部仓库被外传。5月21日
Nx 发布事后报告。5月26日
GitHub 更新文章:正在轮换密钥,包括 GitHub Enterprise Server 签名密钥,并列出管理员需要采取的操作。
- TanStack:范围
- Router/Start 仓库的 42个包、84个版本。Query、DB、Store、Table、Form、Virtual 及其他仓库不受影响。TanStack 表示没有证据显示 npm 令牌被盗
- TanStack:代码做了什么
- 作为安装时脚本运行,收集云、Kubernetes、Vault、npm、GitHub 和 SSH 凭据并发送出去,还试图扩散到受害者维护的其他包
- TanStack:根本原因
- 以下三点的组合:(1) 在
pull_request_target下构建 fork 的代码,(2) 该作业能够写入发布工作流会恢复的缓存,(3) 发布工作流能够签发可用于发布的 OIDC 令牌 - Nx:范围
- 仅 Nx Console v18.95.0(v18.100.0 及之后的版本安全)。Nx CLI、官方
@nx/*插件和 Nx Cloud 不受影响。官方市场统计为28次安装,第二个渠道为41次下载。Nx 自己的分析数据显示约6,000次激活,差异仍在核对中 - Nx:根本原因
- (1) 上游的 TanStack 入侵,(2) 被旧版 pnpm 静默忽略的发布时长设置,(3) 磁盘上可读取的 GitHub CLI 令牌,(4) 允许单个贡献者发布扩展的流水线
- GitHub:范围
- 评估:仅 GitHub 内部仓库被外传。没有证据显示存储在这些仓库之外的客户信息受到影响,例如客户自己的企业、组织和仓库。部分内部仓库确实包含支持沟通摘录等客户信息
- GitHub:应对
- 移除了恶意扩展版本并隔离了终端。按影响从大到小轮换了关键密钥。轮换了包括 GitHub Enterprise Server 签名密钥在内的密钥,并要求管理员轮换公钥。表示调查完成后将发布更完整的报告
阅读提示:“从 GitHub 拿走的仓库数量”不是 GitHub 自己的数字
GitHub 的文章提到了一个被外传仓库的数量,但它把这个数字作为攻击者的说法来介绍,只说与其目前的调查“方向上一致”。本站不把攻击者的说法当作事实,因此这里不转述这个数字。同样,Nx 表示各来源的安装数字不一致,仍在核对中。请不要依据任何数字,而是根据你在该时间段内是否装有受影响的版本来判断。
这条链条本可以在哪里被切断
1. TanStack 的 CI
外部 PR 的代码写入与发布共享的缓存
↓→
在这里切断
不用 pull_request_target / 发布工作流不恢复缓存 / 发布需审批
2. 84个恶意 npm 版本
通过合法路径发布,所以看起来是真的
↓→
在这里切断
发布时长延迟——且工具版本确实支持它
3. Nx 贡献者的电脑
GitHub CLI 令牌从磁盘上的文件被读取
↓→
在这里切断
不留明文令牌文件 / 监控审计日志中的删除操作
4. Nx Console v18.95.0
一个人的权限就能发布扩展
↓→
在这里切断
要求触发者以外的人批准
5. GitHub 员工的设备
投毒扩展,随后内部仓库被外传
↓→
在这里切断
把扩展更新当作依赖对待(见下一节)
这次没能证明安全的东西
- 合法的发布路径和来源证明:TanStack 的恶意版本出自有效的 OIDC 绑定
- 真实的贡献者账户:Nx Console 是用一名真正贡献者的权限发布的
- 分发渠道的自动检查:据 Nx 称,被篡改的版本通过了官方市场的自动验证
- 配置了但实际上没有执行的设置:发布时长设置被旧版 pnpm 静默忽略
本可以切断链条的东西(依据事后报告)
- 发布前由第二个人批准:Nx 在其他仓库已经有这一机制,但 Nx Console 没有
- 把发布工作流与缓存分开:TanStack 事后禁用了缓存
- 真正运行的发布时长延迟:恶意版本在被安装时只发布了77分钟
- 有人阅读常规的发布通知:这是 Nx 唯一的发现途径
本站的看法:扩展的自动更新,就是自动引入依赖
对于 npm 依赖,“不安装最近几天内发布的东西”正逐渐成为常见做法。但编辑器扩展通常默认自动更新,同样的思路还没有跟上。这就是 Nx 写道,开启了自动更新的人应假定已被入侵的原因。而且扩展运行在持有你的 GitHub 和云凭据的机器上,拥有你的权限。在持有生产环境或包发布权限的机器上,考虑用 VS Code 的 extensions.autoUpdate 设置关闭自动更新,过几天后再自己应用更新。代价是安全修复会慢一些,但像这次这样在发布几分钟内就被撤下的版本,仅靠延迟就能避开。
还有一点:这条链条跨越了组织的边界。Nx 贡献者是在一个与 Nx 无关的项目中安装了恶意包,而 GitHub 员工安装的是 Nx 的扩展。你的开发电脑,是你提交代码的每一个项目的供应链的一部分,而不只是你雇主的项目。
信息来源(公开资料)
本文中的事实来自以下公开资料。不涉及攻击手法和识别攻击者的信息。
- TanStack,“Postmortem: TanStack npm supply-chain compromise”(2026年5月11日发布;5月15日更新)— tanstack.com
- TanStack,“Hardening TanStack After the npm Compromise”(事件后的改进)— tanstack.com
- GitHub Advisory Database,“GHSA-g7cv-rxg3-hmpx (CVE-2026-45321)”(受影响版本的完整列表)— github.com
- Nx,“Postmortem: Nx Console v18.95.0 supply-chain compromise”(2026年5月21日)— nx.dev
- Nx Console 安全公告“GHSA-c9j4-9m59-847w”— github.com
- GitHub,“Investigation update: GitHub Enterprise Server signing key rotation”(2026年5月20日发布;5月26日更新)— github.blog
- GitHub Security Lab,“Keeping your GitHub Actions and workflows secure: Preventing pwn requests”(pull_request_target 的安全用法)— securitylab.github.com
- GitHub Docs,“Managing environments for deployment”(必需审阅者)— docs.github.com
更新记录
2026-09-30:初版,依据 TanStack 的事后报告(5月15日修订版)、Nx 的事后报告(5月21日)和 GitHub 的公告(5月26日更新)。GitHub 表示调查完成后将发布更完整的报告;届时本页将更新。
延伸阅读
- 同样的模式及吊销顺序:防御 npm 供应链蠕虫
- 不让密钥进入仓库:用 gitleaks 在提交前拦截密钥 / .env 文件和 API 密钥为什么有风险
- 通过有效凭据发生的入侵:2026年的入侵来自有效凭据
- 保护账户:如何选择多因素认证 / SSH 密钥的最小权限
- 2026年的其他事件:2026年的数据泄露与网络攻击 / Canvas(Instructure)数据泄露
FAQ
QTanStack 的哪些包被投毒了?
根据 TanStack 的事后报告,从 Router/Start 仓库发布的42个包受到影响,每个包两个版本,共84个版本(例如 @tanstack/react-router 1.169.5 和 1.169.8、@tanstack/history 1.161.9 和 1.161.12)。完整列表见 GitHub 安全公告 GHSA-g7cv-rxg3-hmpx(CVE-2026-45321)。Query、Table、Form、Virtual 等其他仓库的包不受影响,TanStack 表示目前发布的所有版本都可以安全安装。
Q如果我安装了受影响的版本,该怎么做?
TanStack 强烈建议,在2026年5月11日(UTC)安装过受影响版本的人,轮换从安装主机能访问到的 AWS、GCP、Kubernetes、Vault、GitHub、npm 和 SSH 凭据。由于代码在安装时运行,除了开发者的电脑,CI 运行器也算在内。
Q我在用 Nx Console,受影响吗?
根据 Nx 的事后报告,只有 Nx Console v18.95.0 受影响,它在2026年5月18日 UTC 12:30 至13:09 之间可以获取。v18.100.0 及之后的版本是安全的。Nx 要求在该时间段内安装了 Nx Console 且开启了自动更新的人,把这台机器视为已被入侵,并轮换所有凭据。Nx CLI(nx 包)、官方 @nx/* 插件和 Nx Cloud 不受影响。
QGitHub 用户的仓库泄露了吗?
据 GitHub 称,此次活动只涉及 GitHub 内部仓库的外传,没有证据显示存储在这些仓库之外的客户信息受到影响,例如客户自己的企业、组织和仓库。部分内部仓库确实包含客户信息,例如支持沟通的摘录,GitHub 表示如果发现任何影响,将通过既定渠道通知客户。GitHub Enterprise Cloud 的客户无需采取任何行动。
QGitHub Enterprise Server 的管理员需要做什么?
GitHub 在5月26日的更新中表示,正在轮换密钥,包括用于签名 GitHub Enterprise Server 更新包的密钥,并要求管理员轮换其实例中的 GPG 公钥。不轮换的话,今后的升级将无法通过验证。操作说明和辅助脚本的 SHA256 摘要见 GitHub 的文章。GitHub 还要求客户只从官方来源下载 GHES 更新。
Q这三起事件有关联吗?
TanStack 与 Nx 之间的关联写在 Nx 的事后报告中:5月11日,一名 Nx 贡献者在一个无关的项目中运行 pnpm install,解析到了被投毒的 @tanstack/zod-adapter 1.166.15,GitHub CLI 令牌因此被盗。GitHub 的文章把入侵其员工设备的“被投毒的 VS Code 扩展”链接到了 Nx Console 的安全公告。
Q根本原因是什么?
TanStack 的事后报告指出了三个只有组合在一起才会生效的弱点:一个 pull_request_target 工作流构建了来自 fork 拉取请求的代码;该作业可以写入与发布工作流共享的 GitHub Actions 缓存;发布工作流可以签发用于发布到 npm 的 OIDC 令牌(每次 CI 运行时签发的短期令牌)。Nx 指出的是:一个被旧版 pnpm 静默忽略的发布时长设置、一个存放在任何本地进程都能读取的位置的令牌,以及一个允许一个人就能发布扩展的流水线。