如果供应链攻击有一条"最方便的裂缝",那往往不是代码本身写错了,而是"合法工具被未受信任的路径污染"。2026 年 8 月底披露的 Trinitite 事件,把这条裂缝展示得一清二楚:一个曾经受欢迎的前端代码生成包 @7nohe/openapi-react-query-codegen,其发布所用的 GitHub Actions 工作流,竟把一条由任意用户发起的 issue_comment 当成发布授权——攻击者借此在 PR 分支上检出受控代码、运行安装流程,最终签发受信任的发布令牌,把十个恶意版本推上了 npm,并继续向 RubyGems 与 PyPI 蔓延。一、根因:一个把"评论"当"授权"的发布工作流Corgea、StepSecurity、Divide 等多家研究机构在 8 月底先后跟进分析,拼出了事件的技术骨架。该项目的发布工作流存在一个危险的信任假定:它把未受信任的 issue_comment 事件视为发布授权。攻击者利用这一逻辑,让工作流在 PR 分支上检出由自己控制的代码,执行 pnpm install,再借助工作流内的 id-token: write 权限签发受信任的发布令牌。于是,攻击者控制的代码被当成了"官方发布"装进了十个恶意版本(0.5.4、0.5.5、1.6.3、1.6.4、2.2.1、2.2.2、3.0.3、3.0.4 及两个预发布版本)。整个链条里没有硬碰任何加密边界,只是让一套正常的工作流,被一个本不该拥有它的人"遥控"了。二、载荷:从下载 Bun,到翻箱倒柜地偷凭据恶意包的投递手法相当隐蔽。部分版本在 binding.gyp 这类构建脚本里做动作,通过遍历 Python 对象触发 os.system() 执行命令;另一些版本则走 preinstall 脚本。加载器先对载荷做 XOR 解码,再用 AES-GCM 解密,随后把 Bun 运行时下载到临时目录执行。落地后的能力清单指向一个清晰的"凭证猎人":它会收集云、Vault、Kubernetes、SSH 与 Git 相关的凭据,并尝试用其中已被验证有效的 npm、RubyGems、PyPI 凭证向其它注册表继续传播——这也解释了为什么这个蠕虫能跨注册表蔓延。对任何安装了受影响版本的主机或 CI runner 而言,都必须默认它们已经失守。三、为什么这次不同:跨注册表的自动复制传统的包投毒大多局限于单一生态。Trinitite 真正让人警觉的,是它把"有效凭据"变成一种可跨生态复制的通用能力:一旦在同一台机器上拿到注册表令牌,它就能同时向 npm、RubyGems、PyPI 推送恶意包,让一次单点入侵横向扩散成多条注册表的污染。这意味着清理远不止"删掉那一个包"——还要追踪它可能已经写入哪些其它注册表的恶意版本,并回滚所有被其窃取的令牌。四、防御与处置- 把受影响版本当失守处理:安装过 @7nohe/openapi-react-query-codegen 受影响版本的主机与 CI runner,应视为被控制,隔离并全盘检查;- 立即轮换一切可能被触及的令牌:npm / RubyGems / PyPI 令牌、GitHub token、云与 Vault 凭证、SSH 与 Git 凭据;- 审计发布工作流的信任边界:任何把 issue_comment、PR 分支或其它未受信输入当作发布授权的工作流都必须修正,遵循权限最小化与"发布即人工/单独令牌"的原则;- 排查跨注册表残留:检查个人与组织在 npm、RubyGems、PyPI 上是否出现了非预期的恶意版本,并作相应撤销。Trinitite 提醒我们,供应链安全的真正闸门,往往不在代码审计本身,而在"谁有资格让一段代码被当成官方版本发出去"。当一套发布工作流可以被一条社交媒体式评论触发、并在其间拿到受信任发布令牌时,攻击者其实已经绕过了几乎所有面向代码的检查。把"谁在什么时候、出于什么输入、签发了什么"彻底管起来,才是堵住这类蠕虫复制的正道。参考:Corgea、StepSecurity 等机构对 Trinitite 的公开研究、GitHub Security Advisory GHSA-9pvf-vcx3-x239 对相关恶意版本的记录。
上一篇一个 GitHub Issue,就够打穿一堆仓库的 CI runner 密钥:Claude Code / Gemini CLI / OpenAI Codex 密钥泄露全复盘——命令验证器剥引号被绕过(CVE-2026-54316)、headless 模式强行信任并加载 .env(CVE-2026-12537 满分)、以及用"下载计数器"逐字符外泄 API key 的通道下一篇你的打印服务器才是最容易失守的入口:PaperCut NG/MF 预认证 RCE 全复盘(CVE-2026-81578 + CVE-2026-82078)——管理接口的认证绕过碰上了不安全动态类加载,9.4 分的组合拳把打印队列变成内网跳板
发表评论