Address findings from pedagogical review simulating a non-expert user: - Add CLAUDE.md to project root (was referenced but missing) - Fix README score from 12/9/1 to 13/8/1 (match feature-map.md) - Add Expected Output sections to examples 01, 02, 05, 09, 10 - Create pipeline-output/ and briefings/ directories - Add example ordering guidance in README - Add plan requirements for examples 11/13 in prerequisites - Add skill frontmatter explanation in GETTING-STARTED.md - Explain Cowork/Dispatch with links in cowork-integration - Expand .gitignore with node_modules and generated output files - Add model override hints in agent frontmatter comments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
92 lines
2.8 KiB
Markdown
92 lines
2.8 KiB
Markdown
# Example 09: Security Hooks
|
|
|
|
**Capability:** Claude Code executes hook scripts before and after every tool call.
|
|
PreToolUse hooks can block dangerous operations. PostToolUse hooks create audit trails.
|
|
|
|
**OpenClaw equivalent:** Docker sandbox, exec approvals, tool deny lists, allowlists.
|
|
|
|
---
|
|
|
|
## How the Hooks Work
|
|
|
|
The `hooks/` directory in this repo contains two scripts:
|
|
|
|
- `pre-tool-use.sh` - runs before every Bash tool call. Blocks destructive patterns.
|
|
- `post-tool-use.sh` - runs after every tool call. Appends to `hooks/audit.log`.
|
|
|
|
Both are registered in `.claude/settings.json` under the `hooks` key.
|
|
|
|
---
|
|
|
|
## The Prompt
|
|
|
|
```
|
|
Try running this shell command: rm -rf /tmp/test-deletion-target
|
|
|
|
Before running it, explain what you expect the PreToolUse hook to do.
|
|
After the attempt, check hooks/audit.log and show me the last 5 entries.
|
|
Then explain what was blocked and why it was flagged by the hook.
|
|
```
|
|
|
|
---
|
|
|
|
## What Happens
|
|
|
|
1. Claude Code calls the Bash tool with `rm -rf /tmp/test-deletion-target`
|
|
2. Before execution, `pre-tool-use.sh` receives the command as input
|
|
3. The hook matches the `rm -rf` pattern and exits with a non-zero code
|
|
4. Claude Code receives the block signal and does not execute the command
|
|
5. `post-tool-use.sh` logs the blocked attempt with timestamp and tool name
|
|
6. Claude Code reports what happened and shows the audit log
|
|
|
|
---
|
|
|
|
## Reading the Audit Log
|
|
|
|
```bash
|
|
tail -20 hooks/audit.log
|
|
```
|
|
|
|
Each entry has the format: `[timestamp] TOOL: bash | STATUS: blocked | CMD: rm -rf ...`
|
|
|
|
---
|
|
|
|
## Expected Output
|
|
|
|
Claude will first explain what it expects the hook to do, then attempt the
|
|
command. You should see something like:
|
|
|
|
```
|
|
I expect the PreToolUse hook (hooks/pre-tool-use.sh) to intercept this
|
|
command because it matches the "rm -rf" pattern in the blocked list...
|
|
|
|
[Claude attempts: rm -rf /tmp/test-deletion-target]
|
|
[Hook blocks the command]
|
|
|
|
The command was blocked by the PreToolUse hook. The hook matched "rm -rf"
|
|
in the command string and returned exit code 2 with a block decision.
|
|
```
|
|
|
|
The audit log (`hooks/audit.log`) will contain an entry like:
|
|
|
|
```
|
|
[2026-03-26T10:15:23] TOOL: bash | STATUS: blocked | CMD: rm -rf /tmp/test-deletion-target
|
|
```
|
|
|
|
**How you know it worked:**
|
|
- The `rm -rf` command was NOT executed (nothing was deleted)
|
|
- Claude reported the hook blocked it
|
|
- `hooks/audit.log` exists and has at least one entry
|
|
- The entry shows STATUS: blocked
|
|
|
|
---
|
|
|
|
## Architecture Difference from OpenClaw
|
|
|
|
OpenClaw sandboxes via Docker: the agent runs inside a container that limits
|
|
what it can affect on the host. Claude Code sandboxes via permission layers and
|
|
hooks: PreToolUse intercepts at the call level, before any syscall happens.
|
|
|
|
For personal use, hooks are more flexible. You write exactly the rules you need.
|
|
For untrusted third-party agents, Docker isolation is stronger. See
|
|
`security/nemoclaw-comparison.md` for a full breakdown.
|