
Introducing AI Coding Agent Governance: Using Hooks to Bring Visibility to the ADLC | Blog | Endor Labs
Endor Labs explains how the hook systems in Claude Code (.claude/settings.json) and Cursor (.cursor/hooks.json) work as deterministic, out-of-band interception points — PreToolUse, beforeSubmitPrompt, afterFileEdit, stop, etc. — that let a security-owned script allow, deny, or rewrite an agent's shell commands, MCP calls, and file edits before they execute. It details the exit-code/stdout-JSON contract for each platform and describes how their endorctl ai-audit command normalizes both vocabularies, streams every agent action to a backend for a centralized audit trail, and enforces 29 default governance policies (shell-command allow/deny lists, sensitive-file patterns, MCP allowlists) server-side across developer machines.
What it is
An Endor Labs blog post arguing that AI coding harness hooks — not the model's own safety training — are the right place to enforce security policy on agents like Claude Code and Cursor. It positions hooks as the same pattern as git hooks, pre-commit, and Kubernetes admission webhooks: platform-defined extension points that hand a decision to an operator-owned script.
How it works
The mechanism the summary already covers (JSON to stdin, decision back via exit code/stdout). The details worth extracting:
Claude's exit-code contract, precisely:
- Exit
0→ harness parses stdout for a JSON decision. - Exit
2→ blocking error: stdout is ignored, stderr is fed back to the model as an error message, and the action is canceled (tool call doesn't run, prompt is erased, or the session can't stop, depending on event). - Any other non-zero → non-blocking error.
Precedence when hooks chain: deny > defer > ask > allow — secure by default.
Why the event counts differ (six vs thirteen): Claude uses a single PreToolUse event with matchers to select behavior per tool. Cursor instead ships separate event-specific hooks for shell, MCP, and file I/O, so endorctl ai-audit cursor wires thirteen entries versus six for endorctl ai-audit claudecode.
What to do
This is a conceptual/vendor post, not an advisory — there are no patches or commands to run. The actionable takeaway for an engineer: hooks give you three things the model layer can't, and they're the concrete reason to implement:
- Deterministic policy — a regex on a shell command line isn't subject to jailbreaks (their example: reliably block
rm -rf /). - Centralized audit — stream every
PreToolUse, shell exec, and file read to a SIEM for a forensic record (machine, repo, prompt). - Defense in depth — the hook is the last line when the model misbehaves and the user clicks "yes" by mistake.
Config lives at .claude/settings.json and .cursor/hooks.json.
Caveats
- The page's config examples and the stdin JChat payload schemas are shown only as trimmed/omitted snippets ("A trimmed-down Claude Code config looks like this:" with no content in the fetched text), so field-level detail must come from vendor docs, not this post.
- The fetched text is truncated mid-sentence describing
updatedInput(the "modify" path), so the modify contract is only partially documented here. - This is Endor Labs marketing for its
endorctl ai-auditproduct; the hook mechanism itself is native to the harnesses and usable without Endor.
The core argument — model layer is non-deterministic and persuadable, so the deterministic out-of-band control belongs in hooks — is the whole point, and the summary already states it. The exit-code semantics and the Claude/Cursor architectural difference above are what the summary does not carry.
Technologies named here
Techniques named here
- Prompt injection via planted content
- Data exfiltration via agent tool use
- Destructive command execution via agent tool use
- Hook-based interception
- Centralized audit logging of agent actions
Related in AI Security
