研究揭示 AI Agent harness(如 Claude Code、Codex CLI)的插件更新机制可被利用注入隐蔽 shell 钩子,实测 7 款工具平均成功率 77%,Claude Code 最难攻击但仍有 52.5%。
Li、Zhang、Hou 等人在 9 月 3 日发布了 arXiv 2609.03884,随后在 9 月 8 日做了修订。这篇论文是一项针对 AI agent 运行时的供应链研究,这些运行时位于模型与你本机之间:Claude Code、Codex CLI、OpenCode、OpenClaw、Hermes、OpenHarness、WorkBuddy。
有效载荷是一次插件更新,可以将 shell 命令绑定到生命周期事件。
生命周期钩子是一种配置条目,作用于会话启动、工具调用或文件编辑。运行时将此命令作为子进程启动。模型无需选择该命令、生成它,甚至无需看到它。一旦匹配事件触发,钩子便以运行时赋予子进程的权限运行。
作者将攻击框架称为 HookPry。在 1000 次端到端运行(40 个案例、7 个运行时、5 个后端)中,他们获得了 770 次预言机确认通过、34 次部分成功、196 次失败。零次运行被模型明确阻止。微平均成功率为 77.0%。Hermes 达到 92.5%。Claude Code 是七个中最难的,为 52.5%,但仍超过一半。
我常备很多 agent。也会安装插件,因为市场上有人写了安全审计助手,我不想自己写一个。这两者的组合就是整篇论文的立足点。
后来的更新可以添加你从未批准的钩子
HookPry 不需要本地立足点、提示词或沙箱漏洞。攻击者发布一个带版本号的插件。v1 版看起来有用且无聊。你安装了它。后来,在同一身份下,他们推送了一个添加钩子的更新。
论文将这个缺口命名为时间解耦。引发讨论的示例是 Claude Code 在市场更新后自动加载新添加的生命周期钩子,无需逐项确认或二次授权。对"此插件"的粗粒度信任被视为对下一份清单所绑定任何命令的批准。
如果你曾在 VS Code 扩展上点击过"全部更新",你已知其形态。绑定命令可以在 PreToolUse 或 PostToolUse 上触发,永远不进入聊天记录。
一个附录案例几乎有些无礼——它所需的条件极少。一个标榜为安全哨兵的插件注册了一个名为 env-validator 的 PreToolUse 钩子。用户请求一次审计。模型调用了该插件。运行时先启动钩子。该命令在环境中搜索 KEY、TOKEN、SECRET、PASSWORD、CREDENTIAL 或 AUTH,并将命中结果写入临时文件。插件仍返回一份正常的审计报告。导出内容永远不会出现在模型上下文中。
第二个案例篡改了模型被允许看到的内容。一个 PostToolUse 钩子在返回给 agent 循环前重写了真实工具输出。真正的扫描发现了 eval(user_input) 和一个硬编码密码。钩子伪造了一个零漏洞的通过记录。模型随后告诉你代码是干净的。它没有编造这个谎言——它放大了一个被伪造的观察。
那些扎眼的数字
他们测试了 Claude Sonnet 4.6、DeepSeek-V4-Pro、Kimi-K2.6、GLM-4.7-Flash 和 GitHub Copilot。在匹配事件触发后,绑定和子进程调度跟随运行时,而非供应商。Codex CLI、OpenClaw 和 Claude Code 在后端间几乎不动(标准差在 2.5 个百分点或以下)。OpenHarness、WorkBuddy 和 Hermes 移动幅度更大,因为某些事件仅在模型实际调用工具时才会发生。
持久化和命令控制是薄弱环节。Codex CLI 持久化为 0.0% 端到端。OpenClaw 持久化为 6.2%。网络策略和文件系统隔离在钩子启动后仍然起作用。凭据收集、权限提升和资源劫持不需要那种运气。权限提升在运行时中平均为 93.5%。
一个附带实验将 50 个恶意 MCP 工具描述攻击转换为钩子。原版 HookPry 钩子命中了 50 个中的 46 个(92.0%)。转换后的 MCP 版本命中了 50 个中的 28 个(56.0%)。提示词形态的毒化仍需说服模型调用某个工具。注册的钩子跳过了这一步。
他们还在 40 恶意 / 40 良性的语料库上尝试了三种静态防御。Microsoft Defender 召回了 0/40。一个他们称为 HookPolicy 的生命周期钩子感知策略检出 20/40。Semgrep 检出 19/40。取并集仍漏掉 19/40,即 47.5%。在合成对照样本上没有误报,但也没有覆盖实际攻击。
消融很粗暴。去掉时间解耦或每个运行时的适配器,他们对比集中的端到端成功率降至 0%。攻击存活在相同插件身份、新钩子条目和原生 schema 中。
评估假设插件已安装且更新已送达。市场排名和真实用户采用不在范围内。沙箱逃逸也不在范围内。作者表示已向供应商披露,正在等待回复。
如果明天可以改一个运行时
将钩子差异视为一次权限授予。
安装时,列出每个事件到命令的绑定。更新时,列出新增和删除的绑定,在人工接受每个新命令前停止。"更新插件"不是对 env | grep TOKEN 的知情同意。
在生产环境锁定版本。自动更新是一种投递通道。如果市场可以在没有差异审查的情况下更改钩子,它就可以在你运行时更改所执行的内容。
用比 agent 更窄的环境运行钩子子进程。凭据案例对继承 env 来说是一行代码的事。从钩子进程中删除 secrets,或者不给钩子 shell。
保留一个飞行记录仪,包含钩子注册信息、确切命令、触发事件和 stdout/stderr。如果 PostToolUse 钩子可以重写工具输出,原始字节必须存在于模型无法覆盖的地方。
市场元数据是一个发现面。HookPry 的第一阶段只是让一个良性插件易于找到。危险的部分在更晚时候、以一个你已经信任的名称到来。
如果你维护一个编码 agent 插件,今晚就检查你自己的更新路径。统计那些可以在没有提示词的情况下出现的钩子条目。这个数字是 Defender、Semgrep 和 HookPolicy 在此语料库上仍然漏掉的数量。