以隐形墨水写成
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 News 与 Phoenix Security 在同一周报道了此事。我们现在写它,是因为它最新的一手,是迄今为止最干净的 一个范例——一个为了直接瞄准代码代理而打造的供应链窃贼。
这些包看起来就像开发者不假思索就伸手去拿的工具:环境加载器、钱包检查器、
构建辅助工具,以及——那个一切的开端——eth-security-auditor,一个
安全审计工具。装上一个,它就做寻常窃密程序的事。但共用的 npm 载荷,一个
名为 trap-core.js 的 48 KB 文件,还多做了一件毫不寻常的事。它会写入
.cursorrules 与 CLAUDE.md。
你看不见的那一行
这两个文件是内部规则。Cursor 读 .cursorrules;Claude Code 读 CLAUDE.md。
它们存在,是为了让仓库告诉代理在这个项目里该如何行事——惯例、该做与
不该做的事——而代理把它们当成常设指令,套用到它在那个文件夹里做的一切。
那是工作区里最受信任的文字,因为理应是你自己写的。
TrapDoor 写进它们,并把写下的东西藏起来。恶意指令用零宽 Unicode 字符编码——
U+200B、U+200C、U+200D、U+FEFF——这些码点文本编辑器根本不会显示。
打开 CLAUDE.md,你看到的是寻常的项目笔记。跑 git 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 的破坏性动作,会遇上一道护栏,无论代理被说动了什么,
它都能拒绝。
在这一切之前,坐着那道在 TrapDoor 的扳机处迎向它的层。整场攻击始于代理读到的 内容——被下毒的规则文件——而 Bromure 在模型据以行动之前,用一个设备端的 注入检测器为不可信的内容打分。 那把指令藏过你编辑器的零宽 Unicode,藏不过打分器:它读同样的字节流, 包含看不见的码点,而一个解码成跑个扫描、把秘密寄出去的规则文件,正是它被 造来标记的形状。它在门口拦下其中大半。一种够新颖的编码仍可能溜过一个分类器, 这正是它坐在用完即弃的盒子之前、而非取而代之的原因。
对你隐形,对窃贼空无
TrapDoor 令人不安的部分不是编码的把戏。而是这把戏,作用在你被告知要信任的 那唯一一个文件上——你为自己的代理写下的规则——而一个查看那个文件的人,看不出 任何不对劲,因为根本没什么好看。检测必须每一次都赢过每一种藏起一行的新 手法。那是一场值得跑的竞赛,设备端的打分器也在跑,但安全不该搁在那里。
Bromure Agentic Coding 把它搁在下面一层。它假设代理终究会读到一道它无法与 真的区分的被下毒指令——不论隐形墨水与否——并确保,当代理去找可窃的秘密时, 秘密是诱饵、钱包在一台它够不到的机器上、出口被把关。扫描照样跑。它只是空手 而回。装上它,给你的代理一本规则书,不论下毒与否,都指向 没有任何值得拿走之物。