有一个细节很刺眼:TanStack Router 相关 npm 包里,package.json 被发现多了 optionalDependencies,指向 @tanstack/setup 的某个 GitHub commit;安装时再通过 prepare 执行 bun run tanstack_runner.js。
这不是普通的“包里塞恶意代码”。它更像一次针对现代开源发布链路的利用:npm、GitHub Actions、OIDC trusted publisher、本地安装脚本,被串成了一条看起来很正常的路径。
已知线索:受影响的是 Router 相关包,不是整个 TanStack
目前材料主要来自 GitHub issue 评论和社区调查。不能写成官方已经完整确认,也不能写成已经修复。
但对依赖 TanStack Router 的团队,风险已经足够高。尤其是项目里用了 latest、自动升级、CI 默认跑安装脚本的情况。
| 问题 | 目前线索 |
|---|---|
| 受影响对象 | TanStack Router 相关多个 npm 最新版本被点名,包括 @tanstack/history、@tanstack/react-router、@tanstack/router-core、@tanstack/react-start 等 |
| 已确认指纹 | package.json 中出现 optionalDependencies,指向 @tanstack/setup 的 GitHub commit |
| 触发方式 | prepare 脚本执行 bun run tanstack_runner.js |
| 可疑载荷 | 疑似包含混淆脚本,材料中提到 router_init.js 等文件线索 |
| 目标凭据 | 疑似窃取 AWS、GCP、Kubernetes、Vault、npm、GitHub、SSH 等凭据 |
| 外传路径 | 调查线索称可能经 Session/Oxen 网络外传 |
| 传播特征 | 疑似枚举受害者维护的 npm 包,并尝试重新发布带类似注入的版本 |
边界也要说清楚。材料明确提到,query、table、form、virtual、store 等包,截至检查时没有发现同一指纹。
所以别把这件事扩大成“TanStack 全线沦陷”。更准确的说法是:TanStack Router 相关包的多个最新版本,被指出存在高风险供应链污染线索。
前端团队现在最现实的动作也很简单:冻结相关依赖升级,检查 lockfile,确认是否安装过被点名的 latest 版本。企业项目如果用了自动合并依赖更新,先暂停这条线。
采购和平台团队也该延后把这些版本纳入生产基线。不是因为 TanStack 不能用,而是因为现在缺少官方完整确认、受影响版本清单和明确处置闭环。
麻烦点:它利用的是“正常安装流程”
这次危险的地方,不在技术花活多深,而在触发路径太正常。
你安装一个依赖。npm 解析 git dependency。源码被拉下来。生命周期脚本开始执行。恶意逻辑跑完后,安装过程甚至可能故意失败。
更别扭的是,它藏在 optionalDependencies 里。失败不一定会让使用者立刻警觉。用户看到的可能只是一次普通安装异常。
这就是供应链攻击最讨厌的样子:它不需要用户主动运行奇怪命令,也不需要开发者点开陌生二进制。它借的是你每天都在用的包管理器和 CI。
处置上也不能粗暴。
有评论者提醒,恶意载荷疑似存在本地 dead-man's switch:监控 GitHub token 是否被吊销;如果发现 token 失效,可能执行删除用户目录的动作。这个说法仍来自调查线索,但足够改变处置顺序。
更稳妥的做法是:
- 先隔离疑似受感染机器和 CI runner,不要继续安装或构建;
- 保留 npm 缓存、lockfile、CI 日志和相关产物,避免证据被覆盖;
- 用不触发安装脚本的方式检查包内容,例如查看 tarball,而不是在生产机上随手
npm install; - 暂停相关 release workflow,核查 GitHub Actions 权限、OIDC trusted publisher 绑定、可触发发布的分支和环境;
- 再分批轮换 GitHub、npm、云厂商、SSH、Vault、Kubernetes 等凭据。
这套动作很麻烦,但比“先吊销一切”更安全。安全事故里,快不是第一原则。可控才是。
真正该盯的变量:CI/OIDC 这台信任机器
我更在意发布来源。
评论线索称,恶意版本的 _npmUser 显示它们可能通过 GitHub Actions OIDC trusted publisher 配置发布。这里的关键信号是:问题未必只是某个长期 npm token 泄露。
如果攻击者拿到的是发布工作流、仓库权限、OIDC 绑定或触发 release 的能力,换 npm token 只能止一部分血。发布链路还在,攻击面就还在。
过去大家守 npm token,像守一把钥匙。现在钥匙变成了一台机器:GitHub Actions 构建,OIDC 证明身份,npm 接受证明,然后发布。
这套设计本身不是错。短期凭据和 trusted publishing,本来就是为了减少长期 token 的风险。
问题在于,安全边界换了位置。
以前要问:谁拿到了 token?
现在要问:谁能改 workflow?谁能触发 release?trusted publisher 绑定到哪个仓库、哪个环境、哪个分支?安装脚本在 CI 里是不是默认放行?维护者账号有没有过宽权限?
“水能载舟,亦能覆舟。”放到 CI/CD 上很贴切。自动化信任机制能减少人为失误,也能把一次入侵包装成一次合法发布。
这里有个历史回声。铁路时代,调度系统让运输效率暴涨;但一旦信号系统出错,事故也会沿着效率网络放大。今天的 npm 和 CI/CD 不完全一样,但逻辑相似:基础设施越顺,错误传播越快。
所以接下来最该观察的,不是社交媒体上谁先喊中招。
更关键的变量有三个:
| 变量 | 为什么重要 |
|---|---|
| 官方受影响版本清单 | 决定团队要回滚哪些版本、锁定哪些范围 |
| 发布链路是否被确认受控 | 决定问题是单次污染,还是发布机器仍可被复用 |
| 恶意载荷与自传播是否坐实 | 决定处置范围是项目依赖,还是维护者账号、CI、云凭据一起清洗 |
这件事如果最终坐实,警示不只给 TanStack。所有把 npm 发布交给 CI 的开源项目,都该重新检查自己的 trusted publisher 配置和发布权限。
自动化不是安全的同义词。它只是放大器。治理清楚,它放大秩序;权限混乱,它放大事故。
这次最该让人停手的,不是某个包名,而是一条太顺的正门。开源生态已经把发布做得越来越丝滑,攻击者也会沿着最丝滑的路走。
