咕噜纪
帖子
咕噜纪官方

咕噜纪官方

@admin镇馆龙发布于 10月11日 11:24

你的 coding agent 钩子可能形同虚设:fail-open 陷阱与三行配置堵上

用 Claude Code、Codex、Cursor 的同学,很多人配过 PreToolUse 钩子:拦截 rm -rf、拦截生产数据库写入、拦截密钥外发。但有个扎心的问题——如果钩子脚本自己崩了、超时了、没启动,拦截还会生效吗?

答案是:默认不会。这叫 fail-open(失败即放行)。

实测:四家全是 fail-open

developersdigest 10 月 9 日更新了一份横向实测,结论很齐:

  • Claude Code:钩子崩溃、超时、起不来,默认放行。
  • Cursor:权限钩子输出 malformed 时会 fail-closed,但崩溃、超时、异常退出码默认放行。
  • Codex:文档里压根没有 fail-closed 开关,文档化的失败路径都是“继续执行 tool call”。
  • Gemini CLI:文档写明,退出码非 0 非 2 就是 warning,动作继续。

触发这篇实测的是 Claude Code 更新日志里的两行:v2.1.294 修了“写成自然语言指令的 prompt/agent 钩子会放行本该拦截的东西”;紧接着 v2.1.295(10 月 8 日)加了 onFailure: "block"——钩子起不来、超时、异常退出码,直接拦截。

抄作业:三步堵上

第一步(Claude Code v2.1.295+): 给每个承担安全职责的 command/HTTP 钩子加上:

{
  "hooks": [
    {
      "type": "command",
      "command": "你的守卫脚本",
      "timeout": 10,
      "onFailure": "block"
    }
  ]
}

注意两点:一是配个短 timeout,别让钩子 hang 住整个流程;二是 prompt、agent、MCP tool 钩子不在 onFailure 覆盖范围,别拿它们当安全门。

第二步(Cursor): 安全钩子加 "failClosed": true。

第三步(Codex / Gemini CLI): 没有开关,就把钩子当“辅助提醒”,真正的边界交给 sandbox 和审批策略(approval policy)。另外一个通用兜底:守卫脚本自己把异常转成 exit code 2,别让它带着非预期退出码裸奔。

一句话总结

钩子是“门卫”,但门卫睡着了门就敞开,等于没门。安全策略的默认值应该是“门卫不在就锁门”。花五分钟检查下你的配置,onFailure / failClosed 配上,今晚睡个安稳觉。

来源:https://www.developersdigest.tech/blog/coding-agent-hooks-fail-open-vs-fail-closed-2026

00

回帖

咕
0/2000

还没人接话

第一条回帖最容易被看见。