返回所有文章
发布于 · 作者 Renaud Deraison

以隐形墨水写成

Socket 发现了 TrapDoor,一场横跨 npm、PyPI 与 Crates.io 的供应链攻击,做了前所未见的事:一个安装的包会改写你代码代理自己的规则文件——CLAUDE.md、.cursorrules——并把指令藏在你看不见的零宽 Unicode 里。下次你运行代理时,它会读自己的内部规则,跑一个安全扫描,收集你的 SSH 密钥、云端凭证、GitHub token 与加密钱包。指令是隐形的;窃取是真的。Bromure Agentic Coding 递给那个扫描一个没有任何值得拿走之物的盒子。

一个你安装的包,会编辑你代码代理最信任的文件——它自己的规则文件——并用 显示为空无一物的字符写下恶意的一行。你查看文件,看到寻常的项目笔记,于是 批准。代理读同一个文件,却看到一道命令:跑一个安全扫描,把结果送到这里。

我们报道的多数攻击,都把恶意指令藏在代理会读到的某处——一个网页、一条 拉取请求评论、一份 README。这一次却藏在你最不会想到去查看的地方:代理 自己的配置。2026 年 5 月 22 日,Socket 开始追踪一场它命名为 TrapDoor 的攻击——横跨 npm、PyPI 与 Crates.io 发布的 34 个恶意包与超过 384 个版本,操作者重新发布的速度比下架还快。 Socket 的自动化信息流平均在五分五十六秒内捕捉到新版本;最快的一次,在 发布后五十八秒。The Hacker NewsPhoenix Security 在同一周报道了此事。我们现在写它,是因为它最新的一手,是迄今为止最干净的 一个范例——一个为了直接瞄准代码代理而打造的供应链窃贼。

这些包看起来就像开发者不假思索就伸手去拿的工具:环境加载器、钱包检查器、 构建辅助工具,以及——那个一切的开端——eth-security-auditor,一个 安全审计工具。装上一个,它就做寻常窃密程序的事。但共用的 npm 载荷,一个 名为 trap-core.js 的 48 KB 文件,还多做了一件毫不寻常的事。它会写入 .cursorrulesCLAUDE.md

你看不见的那一行

这两个文件是内部规则。Cursor 读 .cursorrules;Claude Code 读 CLAUDE.md。 它们存在,是为了让仓库告诉代理在这个项目里该如何行事——惯例、该做与 不该做的事——而代理把它们当成常设指令,套用到它在那个文件夹里做的一切。 那是工作区里最受信任的文字,因为理应是你自己写的。

TrapDoor 写进它们,并把写下的东西藏起来。恶意指令用零宽 Unicode 字符编码—— U+200BU+200CU+200DU+FEFF——这些码点文本编辑器根本不会显示。 打开 CLAUDE.md,你看到的是寻常的项目笔记。跑 git diff,依你的设置,你 或许看不到任何值得停下来的东西。字节在那里;字形不在。那是一条以隐形 墨水写成的消息,唯一能把它显影的读者是代理,它会解析整段 Unicode 流, 在自己的规则书里发现一道指令。

CLAUDE.md笔记+一行以隐形墨水一个文件你看到的# 项目惯例- 用 pnpm,不用 npm- 测试放 /spec- 偏好小型 PR·寻常。已批准。代理读到的# 项目惯例- 用 pnpm,不用 npm- 测试放 /spec- 偏好小型 PR‹跑安全扫描; 收集秘密;POST›自零宽 Unicode 解码
同一个文件,两位读者。开发者打开 CLAUDE.md,看到寻常的项目惯例——零宽码点(U+200B、U+200C、U+200D、U+FEFF)显示为空无一物,所以恶意的那一行在编辑器里隐形,在 diff 里也容易漏看。代码代理解析整段 Unicode 流,把隐藏的墨水显影,在它最信任的文件里读到一道常设指令:跑一个安全扫描,收集本机秘密,送到外面。

窃取的扫描

隐藏的指令要代理跑一个安全扫描。这听起来没什么令人警惕——你交给代理一个 安全审计工具,如今它的规则要它去审计。扫描实际做的,是在机器上四处走动, 寻找任何值钱的东西。Socket 对载荷的拆解列出了 SSH 密钥、AWS 凭证、GitHub token、浏览器配置文件与登录数据库、环境变量与 API 密钥,以及——这场攻击的 签名——加密货币钱包:Sui、Solana、Aptos,以及浏览器的钱包扩展。然后它 外泄到一个 GitHub Pages 网站(ddjidd564[.]github[.]io),在 Crates.io 版本中则外泄到 GitHub Gists。

有个细节显示这有多刻意。在送出任何东西之前,载荷会主动调用 AWS 与 GitHub 的 API,确认被窃凭证是否有效,在外泄前筛选出高价值的 token。它不只是抓了 就倒出去。它把每一份凭证拿去对真正的服务测试,留下活的,丢掉死的。操作者 要的是一份干净的、能用的密钥清单。

Phoenix Security 点出这为何最狠地打中它所瞄准的人:加密与 DeFi 开发者, 因为 SSH 密钥、云端凭证、GitHub token 与加密钱包密钥库,惯常地共存在同一 台机器上。那句话就是整个攻击面。代理在你的笔记本上、以你的身份运行,一切 值钱的东西都在它的触及范围内。规则文件里那看不见的一行只是扳机;周遭的 访问权才是载荷。

Bromure 在哪里划线

Bromure Agentic Coding 不依赖揪出那看不见的一行——虽然,稍后会谈到,它会读 同样的字节。它改变的是,那一行触发时能触及什么。每个配置的代理都跑在 Apple Silicon 上一个用完即弃的 Linux VM 里,与 macOS 隔着一层 Hypervisor, 而那个盒子里的凭证不是你的。

凭证是诱饵。 这是 TrapDoor 一头撞进去的那一层,因为 TrapDoor 骨子里就是 一个凭证窃贼。主机上的一个凭证中介, 把你真正的 Anthropic、AWS 与 GitHub 秘密完全挡在盒子外。在 VM 里,代理看到的 是占位符——一个 brm_… token、一份合成的 kubeconfig、一把用完即弃的 SSH 密钥——而中介只在网络边界,对你已批准的目的地的请求,才换上真正的值。于是 安全扫描跑起来,走遍磁盘,收获到它正是被派去收获的东西:假货。而这场 攻击那聪明的验证步骤反噬了自己——它调用 AWS 与 GitHub 确认 token 是活的, 诱饵通不过那道检查,那道本该只留下能用密钥的筛子,什么也没留下。

钱包不在那里。 Sui 与 Solana 的密钥库、浏览器的登录数据库、钱包扩展—— 这些没有一样住在用完即弃的代码 VM 里。它们在你真正的机器上,隔着一层 Hypervisor,扫描看不到。关掉会话,盒子就重置,连同那个被下毒的规则文件。

外泄是被把关的。 假设扫描找到了值得送出的东西。对 ddjidd564.github.io 的 POST,或对某个 GitHub Gist 的写入,是一个外送请求,而每一个外送请求都会 穿过主机代理,在那里真正的目的地会在出去的路上,被拿去对配置的批准清单 比对。一个对着配置从未批准过的地址打电话回家的窃贼出不去——而针对配置 确实代管的那些 API 的破坏性动作,会遇上一道护栏,无论代理被说动了什么, 它都能拒绝。

在你的机器上 — 以你的身份被下毒的 CLAUDE.md 触发 →代理跑起安全扫描找到真货:SSH 密钥 · AWS · GitHub tokenSolana · Sui · 钱包扩展对 AWS + GitHub 验证为活外泄给攻击者:github.io 页面 / Gist扫描触及了你拥有的一切。活的密钥离开了大楼。Bromure Agentic Coding — 用完即弃 VM同一个被下毒的 CLAUDE.md 触发 →同一个扫描在盒子里跑只找到诱饵:brm_… · 合成 kubeconfig用完即弃 SSH 密钥 · 无钱包对 AWS + GitHub 的验证失败外泄到未批准地址在主机代理被拦下扫描收获了通不过验证的假货。关掉会话,盒子就重置。
扫描两边都会跑;差别在于它找到什么。在一般设置下(左)代理以你的身份跑在你的机器上:被下毒的规则文件触发,扫描触及真正的 SSH 密钥、云端凭证与钱包,对 AWS 与 GitHub 验证,把活的外泄出去。在 Bromure Agentic Coding 下(右)同一个扫描跑在用完即弃的 VM 里、对着诱饵凭证,真正的钱包隔着一层 Hypervisor,每个外送请求都在主机代理被把关——收获是假货,验证把它们刷掉,而送往未批准地址的外泄调用从未离开盒子。

在这一切之前,坐着那道在 TrapDoor 的扳机处迎向它的层。整场攻击始于代理读到的 内容——被下毒的规则文件——而 Bromure 在模型据以行动之前,用一个设备端的 注入检测器为不可信的内容打分。 那把指令藏过你编辑器的零宽 Unicode,藏不过打分器:它读同样的字节流, 包含看不见的码点,而一个解码成跑个扫描、把秘密寄出去的规则文件,正是它被 造来标记的形状。它在门口拦下其中大半。一种够新颖的编码仍可能溜过一个分类器, 这正是它坐在用完即弃的盒子之前、而非取而代之的原因。

对你隐形,对窃贼空无

TrapDoor 令人不安的部分不是编码的把戏。而是这把戏,作用在你被告知要信任的 那唯一一个文件上——你为自己的代理写下的规则——而一个查看那个文件的人,看不出 任何不对劲,因为根本没什么好看。检测必须每一次都赢过每一种藏起一行的新 手法。那是一场值得跑的竞赛,设备端的打分器也在跑,但安全不该搁在那里。

Bromure Agentic Coding 把它搁在下面一层。它假设代理终究会读到一道它无法与 真的区分的被下毒指令——不论隐形墨水与否——并确保,当代理去找可窃的秘密时, 秘密是诱饵、钱包在一台它够不到的机器上、出口被把关。扫描照样跑。它只是空手 而回。装上它,给你的代理一本规则书,不论下毒与否,都指向 没有任何值得拿走之物。