你的编码代理触发了那道为入侵者而建的警报
Sophos 查看了一周的端点遥测数据,发现 AI 编码代理触发了那些用来抓攻击者的同一批规则。被拦截活动中超过一半是凭据访问——代理解密浏览器保存的密码、掏空 Windows 凭据保险库、杀掉浏览器进程以读取其存储。无论谁发起,这种行为都有风险。它之所以能碰到那些存储,只是因为代理跑在你的机器上、以你的身份、带着你的触及范围。把代理挪到一个 hypervisor 之外,端点上就没有任何东西可供它触及了。
Sophos 提取了一周的端点遥测数据,发现编码代理触发了那些为抓入侵者而建 的规则。被拦截活动中的百分之五十六是凭据访问——代理解密浏览器保存的 密码、掏空 Windows 凭据保险库、终止浏览器进程以读取其存储。这些代理 身上没有任何恶意。它们能碰到那些存储,是因为它们跑在你的机器上、以你的 身份、带着你所能触碰的一切。
一位开发者打开 Claude Code,让它查点东西,然后去倒咖啡。回来的路上, 端点代理给这次会话打了标记:某个进程刚刚用一个 Windows 系统 API 解密了 浏览器保存的凭据 blob。那是教科书式的信息窃取器动作。而这一次,它也正是 编码代理在做别人交代它的事——用实用的方式读取一个登录后才可见的页面, 解锁浏览器早已保存好的那个密码。
Sophos X-Ops 花了 2026 年 6 月的一周来清点这些碰撞。他们从 Windows 端点上 的行为引擎里取出拦截型和静默型的规则命中,按唯一机器计数,并按 MITRE ATT&CK 战术 排序。图景毫不含糊。在拦截型规则中,凭据访问占了 56.2%, 执行占 28.8%。单条最大的凭据规则——占该组的 42.6%——在某个进程使用 Windows 数据保护 API(即 DPAPI,那个解锁程序此前存下的机密的操作系统服务) 时触发。那正是信息窃取器把浏览器加密的密码文件还原成明文时所做的调用。 如今它也是编码代理在某个技能需要一个已登录页面时所做的调用。
攻击者的行为,善意的意图,同一份遥测
Sophos 捕捉到的这条链上,每一步都是开发者能认出的工具。一个叫 GStack 的
"技能包"——一捆你装进代理的现成能力——附带一个 /browse 技能。当代理用它时,
进程树跑的是 bash → browse.exe → node → PowerShell,而那个 PowerShell
加载 System.Security,对浏览器保存的数据调用 DPAPI 的 Unprotect。
Sophos 捕捉到这条链在 Claude Code 之下运行。那一周的其他地方还有:
用 cmdkey /list 枚举 Windows 凭据管理器,按 PID 对浏览器进程用
taskkill 好让它们的凭据文件可被自由读取,用 certutil 和 bitsadmin
——两个签名过的 Windows 实用工具——去取一个 Python 安装程序,以及
PowerShell 往启动文件夹里写一个脚本,好让它在下次登录时运行。
把"编码代理"这几个字去掉再读这份清单,那就是一次入侵。凭据窃取、 就地取材(living-off-the-land)二进制文件——攻击者借用的那些签名过的操作 系统工具,好让没有任何陌生东西冒出来——以及一个持久化立足点。行为引擎对 这一切触发是对的。Sophos 对结论很谨慎:这是"第一遍、一次简短的信号转储", 不是普查,检测也不意味着这些代理是恶意的。它们所意味的更窄也更持久。这些 动作中有一些,无论谁发起都有风险,用他们的话说,"由一个 AI 代理来做, 并不会让它们变得安全"。
问题在于触及范围,而非意图
同一条规则既抓贼又抓助手,原因在于:在正常配置里,它们站在同一个位置。
代理以你的用户账户、在你的机器上运行。那个账户能打开浏览器保存的密码,
因为是你保存的。它能读 Windows 凭据管理器,因为那个保险库是你的。它能往
启动文件夹里写、能调用 certutil,因为你运行的每一个程序都能。代理一启动,
就继承了你全部的环境权限——每一个机密、每一个签名工具、磁盘上每一个可写的
角落。于是一次提示注入、一个被投毒的技能,或一个过于卖力的正当任务,就有了
这一切可供施展。
正因如此,Sophos 把难点定位为策略,而非检测:"应该允许代理在端点上做什么? 应该强制哪些边界?"他们的调优建议把规则一分为二。有些应当学习代理的 已知良性签名,好不再狼来了地乱叫。另一些"应当继续触发,因为它们抓到的活动, 无论由人还是代理发起都有风险"——DPAPI 解密和凭据保险库转储就在其中。而这就 把防御者留在了真正的两难里。为让代理安静而抑制凭据规则,你就会对做出相同 调用的信息窃取器失明。让它继续触发,你的队列就会被自家开发者装的一个工具 填满。两种选择都不好,因为两者都假定代理必须住在端点上、紧挨着机密。
挪走代理,那个保险库就不在那儿等着被打开
只有当代理住在机密旁边时,这个两难才成立。
Bromure Agentic Coding 让每个编码代理在一台一次性的
Linux 虚拟机里运行,离你的 Mac 一个 hypervisor 之远。代理的世界就是那台
虚拟机。你的 macOS Keychain 不在其中。你保存密码的那个浏览器配置文件不在
其中。没有 Windows 凭据管理器,没有宿主的启动文件夹,没有可供终止和翻查的
宿主浏览器进程。当某个技能像 GStack 的 /browse 那样去够保存密码的存储时,
这一够,落进的是一台从未持有过那些密码的全新虚拟机。调用可以运行;它找不到
任何值得拿走的东西。
剩下的是代理干活确实需要的凭据——模型的 API 密钥、推送分支用的 GitHub
令牌、部署用的 AWS 机密。把它们交给虚拟机,只会把你刚搬离的那个保险库
重建出来。Bromure 不交给它。宿主上的一个中间人代理,坐在虚拟机与外部世界
之间的线路上。在虚拟机内部,代理只握着假货——本该是真密钥的地方,是一个
brm_… 的占位字符串。当代理向 api.anthropic.com 或 github.com 发出
请求时,代理在出去的路上把假货换成真值,在回来的路上再换回来。真正的机密
只在需要它的那一跳里存在,从不进入虚拟机的内存。一个把自己环境里能找到的
一切都解密的代理,最后带走的只是占位符。
让人类留在回路里的两条规则
隔离把机密挪出了触及范围;另外两个控制决定一个真机密何时才被允许离开宿主。
每一次凭据替换都可以设置为需要批准——从假到真的替换会暂停,你 Mac 上的
一个对话框会在真值出去之前询问。对于一个 SSH 密钥或一个 AWS 请求,你授予它
五分钟、一个小时,或本次会话的其余时间,然后它再次上锁。而对于通过代理接进来
的数据库——MongoDB、ClickHouse、Elasticsearch——一道护栏会读取线路上实际的
操作,并能拦下破坏性的那些,于是一个代理自己说服自己发出的 DELETE,即便在
凭据被换入之后,也永远到不了真正的端点。
这一切都没有要求代理守规矩。它假定代理可能会去做那件攻击者形状的事——解密 一处存储、掏空一个保险库、重试一次被拦的下载——因为 Sophos 刚刚看着真实的 代理做了正是这些。设计决定:当它发生时,存储是空的,密钥是假的,破坏性的 查询在门口就被拦住。
代理如今的行为,正像你的防御被调校去阻止的那个东西,而你没法靠请它守规矩来 解决这件事。你靠改变它们所站的位置来解决。给一个代理一台没有保存密码的一次性 机器、一个装满假货的保险库,以及一个把真机密留在宿主上的代理——那份点亮了 Sophos 转储的遥测,就变成一个在空房间里翻找的进程。 装上它,把它指向一个仓库,任它去够它想要的任何东西。