Skip to content

[Bug] PreToolUse hook exit 2(block)被平台间歇性丢弃:hook 正确返回拦截但命令仍执行(约 23%) #906

Description

@seasonmsg

提交前确认 · Pre-submission checklist

问题类别 · Category

Bug(hooks 机制)

涉及的 Agent 框架 · Agent framework

ZCode 桌面版(Windows)——PreToolUse hooks(用户级 config 注册,Bash matcher)

严重程度 · Severity

高:PreToolUse 是安全护栏通道(拦截危险命令/保护文件写入),裁决被丢弃 = 护栏间歇失效,且失效形态对上层不可见(命令静默执行成功)。

复现频率 · Reproducibility

间歇性:同会话同载荷,13 次应拦事件丢 3(≈23%,单审计窗统计,样本小非确率)。单次不可确定性复现,需批量统计复现。

问题描述 · Description

PreToolUse hook 脚本对命中规则的 Bash 工具调用返回 exit 2(block 语义)+ stderr 拦截理由时,ZCode 平台层间歇性不采纳该裁决——对应命令仍被执行。hook 本体已排除嫌疑(证据四链见下),丢失发生在平台对 hook 裁决的分发/合并处理层。

复现步骤 · Steps to reproduce

  1. 注册一个 PreToolUse hook(Bash matcher),逻辑为无条件拦截:读 stdin 后 stderr 输出一行理由,process.exit(2);同时在 hook 入口写一行心跳日志(时间戳+pid),用于区分「hook 没被拉起」与「裁决被丢弃」。
  2. 会话中连续发起 N 次(建议 ≥15)任意 Bash 命令。
  3. 三方对账:hook 心跳日志(每次都该在场)/ 拦截台账(hook 自记)/ 工具执行结果。

期望表现 · Expected behavior

exit 2 + stderr → 该次工具调用被阻止、命令不执行、拦截理由注入模型上下文——每次都应如此。

实际表现 · Actual behavior

约 23% 的命中事件中命令仍被执行。证据四链(单次实例,2026-10-02T07:03:50.596Z,摘自审计台账):

  1. hook 进程被拉起:心跳日志在场 {ts:07:03:50.596Z, pid:8900}(同刻并行另一 hook 07:03:50.484 亦在场);
  2. stdin 已送达:hook 内读异常/空串两路径均有留痕逻辑(在位),该时刻零记录;
  3. 同载荷直调 hook 脚本 100% exit 2(20/20 对照);
  4. 命令仍执行:exit 0、效果落盘。

对照面:同会话 Edit 工具路径(插件层 hooks.json 注册的 PreToolUse)零丢失;config 层注册的多个 Bash 闸有采纳有丢失——间歇、非按闸/按层恒定。

ZCode 版本 · ZCode version

3.14.4.7912(案发窗口与当前实测同版)

设备 / 系统 · Device / OS

Windows x64(10.0.26200),桌面版

截图 / 录屏 / 日志 · Screenshots / Recordings / Logs

可按需补充心跳日志/拦截台账/工具结果三方对账原文(脱敏后)。定位线索供参考:app 内部见 hook 相关 60s 默认超时与 hookInvocation 遥测 schema,但本机 ZCode 数据库中无对应落地表——建议排查 PreToolUse 裁决合并/分发层(是否超时竞态、裁决合并选择性采纳、或遥测丢写同源)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions