Part 6 · Inside a Production Coding Agent

Hooks: Only Explicit Deny Blocks

Verifying lifecycle events, matchers, PreToolUse blocking, and fail-open semantics on errors

THE QUESTION THIS PAGE ANSWERS

ANSWER FIRST

What is the key idea behind “Hooks: Only Explicit Deny Blocks”?

Verifying lifecycle events, matchers, PreToolUse blocking, and fail-open semantics on errors

DECISION RULE

Make the claim earn its place. Use this page as a decision aid, not a definition to memorize. Connect the idea to one real task, one observable result, and one failure that would change your mind.

TRY NEXT

Write one question you could answer with evidence after trying this idea.

WATCH FOR

A conclusion that sounds complete but leaves the key assumption untested.

Grok Build Source Course · 12 / 19

Hooks: Explicit Deny to Block

Think of Hooks as programmable checkpoints on events. PreToolUse can return an explicit deny; process crashes, timeouts, and unparseable output all go fail-open, letting the tool call proceed.

15 event namesPreToolUse can blockJSON configprocess stdin / stdout
01 / OBJECTIVES

Learning Objectives

Distinguish Two Types of Outcomes

Identify explicit Deny versus Hook execution failure — they produce opposite results for the tool call.

Understand Event Matching

Master the matcher's exact name, regex pattern, and Bash compatibility alias.

Write Testable Configuration

Configure a command Hook following the user guide's JSON structure and design four fault-path tests.

02 / CORE VISUAL

The Decision Path of a Single PreToolUse

03 / EVENTS

The Event Surface in Source Code

Session & Tool

Eight Main-Flow Checkpoints

SessionStart, SessionEnd, Stop, StopFailure, PreToolUse, PostToolUse, PostToolUseFailure, PermissionDenied. Only PreToolUse has is_blocking() returning true.

User, Agent & Compaction

Seven Extended Checkpoints

UserPromptSubmit, Notification, SubagentStart, SubagentStop, compatibility alias SubagentEnd, PreCompact, PostCompact.

Key Boundary

"Event Triggered" ≠ "Controls the Main Flow"

The event enum defines trigger points; is_blocking() separately declares blocking capability. When reading the event list, also trace how results are returned to the caller.

crates/codegen/xai-grok-hooks/src/event.rs
04 / SEMANTICS

Block vs. Fail-open Matrix

Hook Result
Dispatcher Interpretation
Tool Call
JSON decision = deny
Explicit deny
Blocked
No valid JSON, exit code 2
Fallback deny
Blocked
Valid JSON allow, exit code 2
JSON takes priority
Allowed, conflict warning logged
Exit code not 0 or 2
HookRunResult::Failed
Allowed, warning logged
Timeout or process crash
HookRunResult::Failed
Allowed, warning logged
Invalid stdout or unknown decision
Fallback exit code or Failed
Output alone does not block; fallback exit code 2 still denies

Security Implication: Hooks are appropriate for policy advisories, auditing, and recoverable pre-checks. When enforcement guarantees are required, the permission layer and sandbox should also be used. Source code comments explicitly require that Hook failures must not break tool availability.

05 / SOURCE

Real Source Evidence

dispatcher.rs

Failure Defaults to Allow

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

Matching and Exit Codes

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)
}

The compatibility mapping lets Bash in configuration hit the internal tool name run_terminal_command. Matchers are compiled from regex; the user guide examples use tool names.

crates/codegen/xai-grok-hooks/src/matcher.rs · runner/command.rs
06 / CONFIG

Configuration Written in the Real JSON Structure

~/.grok/hooks/*.json · project/.grok/hooks/*.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bin/safe-shell-guard.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

The configuration hierarchy is "event → matcher group → handler list". Commands receive the event envelope via stdin; a valid JSON decision takes priority — if no valid JSON is present, the exit code is interpreted, with exit code 2 expressing denial. Global Hooks live in ~/.grok/hooks/; project Hooks live in .grok/hooks/ and are controlled by folder trust. Reserved environment variables are filtered out, and unresolved variables cause an error before startup.

crates/codegen/xai-grok-hooks/examples/hooks/safe-shell.json · xai-grok-pager/docs/user-guide/10-hooks.md
07 / LAB

Lab Exercise: Verify Four Paths

25 MIN

Deliverable
Config, script, test log

  1. Configure a PreToolUse command Hook matching Bash.
  2. Make the script return JSON deny for rm -rf and record the blocked tool result.
  3. Successively trigger exit code 1, timeout, and invalid stdout — verify all three go allowed and produce warnings.
  4. Change the exit code to 2, then verify that invalid stdout can still reach the explicit deny path.
  5. Write a one-sentence boundary statement: which policy must be moved to the permission layer or sandbox.
Takeaway

To judge whether a Hook is safe, ask two questions: can it express an explicit deny, and what does the main flow do when the Hook itself fails? Grok Build's answer is clear — explicit deny blocks, Hook failure goes fail-open.

Source Snapshot Note: This page is based on the hooks crate, user guide, and example configurations from the local grok-build-main snapshot. Code excerpts are for teaching purposes, with log fields and error wrappers omitted; event names, JSON hierarchy, exit codes, and decision semantics match the source.

Where the risk boundary sits in “Hooks: Explicit Deny to Block”

“Think of Hooks as programmable checkpoints on events.” moves security beyond telling a model not to make mistakes. The real protection is ensuring that a mistaken judgment cannot become an irreversible result through permissions, data, or the environment.

Separate model suggestions from real authority

In the flow described by “Identify explicit Deny versus Hook execution failure — they produce opposite results for the tool call”, check what the user may request, what the model may suggest, what the tool actually permits, and who can approve a write or send action. Web pages, documents, and tool results can carry untrusted instructions; looking like documentation does not grant them authority.

  • Configure a PreToolUse command Hook matching Bash
  • Make the script return JSON deny for rm -rf and record the blocked tool result
  • Successively trigger exit code 1, timeout, and invalid stdout — verify all three go allowed and produce warnings

Security includes failure and recovery

Use “To judge whether a Hook is safe, ask two questions: can it express an explicit deny, and what does the main flow do when the Hook itself fails?” for a reverse exercise: add bad input, a missing credential, or an approval that never arrives. Confirm that the system refuses, pauses, and leaves a trace instead of executing to completion.

From “Hooks: Explicit Deny to Block” to “Distinguish Two Types of Outcomes”

“Hooks: Explicit Deny to Block” grounds the problem in “Think of Hooks as programmable checkpoints on events. PreToolUse can return an explicit deny; process crashes, timeouts, and unparseable output all go fail-open, letting the tool call proceed”. “Distinguish Two Types of Outcomes” then moves it toward “Identify explicit Deny versus Hook execution failure — they produce opposite results for the tool call”. Together, they show that the lesson is not just a conclusion to remember, but a claim with conditions.

Carry the judgment into the next situation

For security, separate what the model wants to do from what the system permits. Check data boundaries, tool permissions, human confirmation, and recovery after failure.

  • “Hooks: Explicit Deny to Block”: Think of Hooks as programmable checkpoints on events. PreToolUse can return an explicit deny; process crashes, timeouts, and unparseable output all go fail-open, letting the tool call proceed
  • “Distinguish Two Types of Outcomes”: Identify explicit Deny versus Hook execution failure — they produce opposite results for the tool call
  • “The closing point”: Write a one-sentence boundary statement: which policy must be moved to the permission layer or sandbox

The final “The closing point” brings the discussion to “Write a one-sentence boundary statement: which policy must be moved to the permission layer or sandbox”. The useful thing to carry forward is knowing which judgments must be revisited when input, scale, or risk changes.

Mark as learned Your reading progress updates automatically
← PreviousNext →

Keep reading

The next useful article in the thread.

ARTICLE DISCUSSION

Leave one useful thought here.

Keep the idea that clicked, the question that stayed open, or a small note for the next learner.

Discussing Hooks: Only Explicit Deny Blocks Inside a Production Coding Agent
3discussionsArticle discussion · synced with the Circle
View in the learning circle
AM
Asha MorganContent editor
INSIGHTField note

I turned one judgment from this article into a small experiment I could run today. Knowing what to observe next is more useful than simply remembering the conclusion.

ARTICLE DISCUSSION7 helpful
LH
Lin HarperIndie developer
INSIGHTInsight

After reading this, I first looked for the conditions behind the idea instead of copying the method into a project. That order made the later trade-offs much clearer.

ARTICLE DISCUSSION5 helpful
KM
Kiki MooreProduct operations
QUESTIONQuestion

When this judgment reaches real work, which constraint should be added first? I am curious which step matters most between reading and the first practical attempt.

ARTICLE DISCUSSION4 helpful