1123 字
约 3 分钟
1
Hooks:明确 deny 才阻断
无标签

Grok Build Source Course · 12 / 19 Hooks: 明确 deny 才阻断 把 Hook 看成事件上的可编程检查点。 PreToolUse 可以返回明确拒绝,进程崩溃、超时和不可解析输出则走 fail-open,让工具调用继续。

15 个事件名 PreToolUse 可阻断 JSON 配置 进程 stdin / stdout

一句话速览 核对生命周期事件、matcher、PreToolUse 阻断和故障 fail-open 语义 01 / OBJECTIVES 课程目标

分清两类结果 识别显式 Deny 与 Hook 自身执行失败,它们对工具调用产生相反结果。 读懂事件匹配 掌握 matcher 的精确名、正则模式与 Bash 兼容别名。 写出可测试配置 按用户指南的 JSON 结构配置命令 Hook,并设计四条故障测试。

02 / CORE VISUAL 一次 PreToolUse 的决策路径

PreToolUse 事件信封写入 stdin matcher 工具名命中才执行 运行 Hook 命令 / timeout 解释结果 decision / exit 失败:ALLOW crash / timeout / invalid result 明确 DENY:BLOCK JSON deny / fallback exit 2

03 / EVENTS 源码中的事件面

会话与工具 八个主流程检查点 SessionStart 、 SessionEnd 、 Stop 、 StopFailure 、 PreToolUse 、 PostToolUse 、 PostToolUseFailure 、 PermissionDenied 。其中只有 PreToolUse 的 is_blocking() 为真。 用户、代理与压缩 七个扩展检查点 UserPromptSubmit 、 Notification 、 SubagentStart 、 SubagentStop 、兼容别名 SubagentEnd 、 PreCompact 、 PostCompact 。 关键边界 「事件被触发」不等于「能控制主流程」 事件枚举负责定义触发点, is_blocking() 单独声明阻断能力。读取事件列表时,要同时追踪结果如何回到调用方。 crates/codegen/xai-grok-hooks/src/event.rs

04 / SEMANTICS 阻断与 fail-open 矩阵

Hook 结果 dispatcher 解释 工具调用 JSON decision = deny 显式拒绝 阻断 无有效 JSON,退出码 2 fallback 拒绝 阻断 有效 JSON allow ,退出码 2 JSON 优先 放行并记录冲突警告 退出码非 0 且非 2 HookRunResult::Failed 放行并记录警告 超时或进程崩溃 HookRunResult::Failed 放行并记录警告 stdout 无效或 decision 未知 回退退出码或 Failed 输出本身不阻断;fallback 退出码 2 仍拒绝

安全含义: Hook 适合策略提醒、审计和可恢复的前置检查。需要强制保证时,还应使用权限层与沙箱。源码注释明确要求 Hook 故障不能破坏工具可用性。

05 / SOURCE 真实源码证据

dispatcher.rs 失败默认放行

match result {
 HookRunnerResult::Decision(
 HookDecision::Deny { reason, .. }
 ) => {
 return PreToolUseResult {
 decision: HookDecision::Deny { ... },
 results: run_results,
 };
 }
 HookRunnerResult::Failed(err) => {
 tracing::warn!(
 error = %err,
 "hook failed; ignoring (fail-open)"
 );
 }
 _ => {}
}

crates/codegen/xai-grok-hooks/src/dispatcher.rs

matcher.rs + command.rs 匹配与退出码

pub const DENY_EXIT_CODE: i32 = 2;

pub fn matches(&self, tool_name: &str) -> bool {
 self.regex.is_match(tool_name)
 || self.matches_compat_alias(tool_name)
}

兼容映射让配置里的 Bash 可命中内部工具名 run_terminal_command 。匹配器由正则编译,用户指南示例使用工具名。 crates/codegen/xai-grok-hooks/src/matcher.rs · runner/command.rs

06 / CONFIG 配置按真实 JSON 结构书写

~/.grok/hooks/.json · project/.grok/hooks/.json

{
 "hooks": {
 "PreToolUse": [
 {
 "matcher": "Bash",
 "hooks": [
 {
 "type": "command",
 "command": "bin/safe-shell-guard.sh",
 "timeout": 5
 }
 ]
 }
 ]
 }
}

配置层级是「事件 → matcher 组 → 处理器列表」。命令从 stdin 接收事件信封;有效 JSON 决策优先,无有效 JSON 时再按退出码解释,退出码 2 表达拒绝。全局 Hook 位于 ~/.grok/hooks/ ,项目 Hook 位于 .grok/hooks/ 且受 folder trust 控制。保留环境变量会被过滤,未解析变量会在启动前报错。 crates/codegen/xai-grok-hooks/examples/hooks/safe-shell.json · xai-grok-pager/docs/user-guide/10-hooks.md

07 / LAB 课堂练习:验证四条路径

25 MIN 提交物 配置、脚本、测试记录

配置一个匹配 Bash 的 PreToolUse 命令 Hook。 让脚本对 rm -rf 返回 JSON deny ,记录工具被阻断的结果。 依次制造退出码 1、超时、无效 stdout,验证三者均放行并产生告警。 将退出码改为 2,再验证无效 stdout 下仍可走明确拒绝路径。 写一句边界说明:哪条策略必须移到权限层或沙箱。

Takeaway 判断 Hook 是否安全,先问两个问题:它能否表达明确拒绝,以及它自己失效时主流程如何处理。Grok Build 的答案很清楚,显式 deny 阻断,Hook 故障 fail-open。 源码快照说明: 本页依据本地 grok-build-main 快照中的 hooks crate、用户指南与示例配置整理。代码片段为教学截取,省略日志字段和错误包装;事件名、JSON 层级、退出码与决策语义保持源码一致。

Hooks:明确 deny 才阻断
http://www.clxhxhhr.top/posts/4008/
作者
clxstart
发布于
2026-09-25
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。