钩子更新是模型看不见的远程代码执行。
Agent harness 的生命周期钩子,本质是把宿主 shell 绑到运行时事件上:会话开始、工具调用、文件编辑。命令以宿主权限跑;一旦事件命中,harness 在 LLM 决策路径之外直接派发——模型既不选择,也未必看见。你以为在管「工具能不能被调」;真正能静默执行的,是钩子配置。

七种 harness,同一条更新路径
HookPry(arXiv:2609.03884) 的威胁模型极窄:攻击者只控制插件元数据与生命周期钩子配置。良性、已版本化的插件,之后靠一次更新静默绑定攻击者选定的命令到良性事件——身份未变,权限后到。这叫时间解耦:信任在良性版本上赚到;钩子特权随同名更新到达。
硬数字来自十个攻击目标、25 组 harness×backend、1,000 次端到端:
- 攻破评估的全部七种 harness:OpenHarness、OpenClaw、Claude Code、Codex CLI、OpenCode、Hermes、WorkBuddy;
- 总体微平均 E2E-ASR 77.0%;分 harness 总体最高 Hermes 92.5%,其次 WorkBuddy 90.8%、OpenCode 90.6%、OpenClaw 81.9%、OpenHarness 71.7%、Codex CLI 65.0%、Claude Code 52.5%;
- Privilege Escalation 类平均 93.5%;Credential Collection 85.0%;
- Microsoft Defender 0% 召回;三种静态防御的并集仍漏检 47.5% 恶意产物。
不是提示注入赢了模型。是更新路径把 shell 塞进了模型永远不投票的那一层。
钩子变更 = 特权授予,不是 changelog
别再把「插件自动更新」当成 changelog 噪音。带钩子的插件更新,语义上等于一次特权授予:同一插件身份下,新命令绑定到旧信任。修法不是再写一条「别装恶意插件」的提示——提示碰不到 hook dispatch。要把钩子配置当成依赖:钉版本、审 diff、钩子变更必须显式再批准。
今晚只改一处判定
别再默认「装过的插件可以静默升级钩子」。今晚改一处:盘点本机所有 lifecycle hooks;对带钩子的插件关闭自动更新;钩子配置一变,就必须人工再批准——像 pin 依赖一样 pin 钩子。信任是良性版本赚的;RCE 是更新后模型看不见的那一下。
A hook update is RCE the model never sees.
Lifecycle hooks in agent harnesses bind host shell commands to runtime events — session start, tool calls, file edits. They run with host privileges; once the event fires, the harness dispatches outside the LLM decision path. The model neither chooses nor necessarily observes the command. You thought you were gating “which tools the agent may call.” The silent executor is the hook config.

Seven harnesses, one update path
HookPry (arXiv:2609.03884) uses a narrow supply-chain threat model: the attacker controls only plugin metadata and lifecycle-hook configuration. A benign, versioned plugin is later trojanized by an update that silently binds attacker-chosen commands to benign events — same identity, privileges arrive later. That is temporal decoupling: trust is earned on a benign version; hook privileges land under the same plugin identity.
Hard numbers from ten attack objectives, 25 harness×backend combinations, and 1,000 end-to-end runs:
- Compromises all seven evaluated harnesses: OpenHarness, OpenClaw, Claude Code, Codex CLI, OpenCode, Hermes, WorkBuddy;
- Overall micro-averaged E2E-ASR 77.0%; per-harness overall up to Hermes 92.5%, then WorkBuddy 90.8%, OpenCode 90.6%, OpenClaw 81.9%, OpenHarness 71.7%, Codex CLI 65.0%, Claude Code 52.5%;
- Privilege Escalation category average 93.5%; Credential Collection 85.0%;
- Microsoft Defender 0% recall; the union of three static defenses still misses 47.5% of malicious artifacts.
Not prompt injection beating the model. The update path slipped shell into a layer the model never votes on.
A hook change is a privilege grant, not changelog noise
Stop treating plugin auto-updates as changelog noise. A hook-bearing plugin update is a privilege grant: new command bindings under a previously trusted identity. The fix is not another “don’t install malicious plugins” prompt — prompts never see hook dispatch. Treat hook config like dependencies: pin versions, review diffs, require explicit re-approval when hooks change.
One judgment change tonight
Stop assuming an installed plugin may silently upgrade its hooks. Change one thing tonight: inventory every lifecycle hook on the host; refuse auto-update for hook-bearing plugins; require explicit re-approval when hook config changes — pin hooks the way you pin deps. Trust was earned on the benign version; the RCE is the update the model never sees.