分清兩類結果
識別顯式 Deny 與 Hook 自身執行失敗,它們對工具呼叫產生相反結果。
把 Hook 看成事件上的可程式化檢查點。PreToolUse 可以返回明確拒絕,行程崩潰、超時和不可解析輸出則走 fail-open,讓工具呼叫繼續。
識別顯式 Deny 與 Hook 自身執行失敗,它們對工具呼叫產生相反結果。
掌握 matcher 的精確名、正則模式與 Bash 相容別名。
按使用者指南的 JSON 結構配置命令 Hook,並設計四條故障測試。
SessionStart、SessionEnd、Stop、StopFailure、PreToolUse、PostToolUse、PostToolUseFailure、PermissionDenied。其中只有 PreToolUse 的 is_blocking() 為真。
UserPromptSubmit、Notification、SubagentStart、SubagentStop、相容別名 SubagentEnd、PreCompact、PostCompact。
事件列舉負責定義觸發點,is_blocking() 單獨宣告阻斷能力。讀取事件列表時,要同時追蹤結果如何回到呼叫方。
deny2allow,退出碼 2安全含義:Hook 適合策略提醒、審計和可恢復的前置檢查。需要強制保證時,還應使用權限層與沙箱。原始碼註釋明確要求 Hook 故障不能破壞工具可用性。
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
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。匹配器由正則編譯,使用者指南示例使用工具名。
{
"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 控制。保留環境變數會被過濾,未解析變數會在啟動前報錯。
提交物
配置、腳本、測試記錄
Bash 的 PreToolUse 命令 Hook。rm -rf 返回 JSON deny,記錄工具被阻斷的結果。判斷 Hook 是否安全,先問兩個問題:它能否表達明確拒絕,以及它自己失效時主流程如何處理。Grok Build 的答案很清楚,顯式 deny 阻斷,Hook 故障 fail-open。
原始碼快照說明:本頁依據本地 grok-build-main 快照中的 hooks crate、使用者指南與示例配置整理。程式碼片段為教學擷取,省略日誌欄位和錯誤包裝;事件名、JSON 層級、退出碼與決策語義保持原始碼一致。