1
0
Fork 0
claude-code-complete-agent/security/hook-based-guardrails.md
Kjell Tore Guttormsen 2491f5c732 feat: initial companion repo for OpenClaw vs Claude Code article
40 files demonstrating every major OpenClaw capability using Claude Code:
- 3 agents (researcher, writer, reviewer)
- 3 skills (daily-briefing, slack-message, web-research)
- 2 security hooks (pre-tool-use blocker, post-tool-use logger)
- 10 self-contained examples with copy-paste prompts
- Complete feature map (20 capabilities, 11 full match, 7 different, 2 gap)
- Security docs including NemoClaw comparison
- Automation, messaging, browser, memory documentation

Zero dependencies. Clone and run.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 09:47:29 +01:00

2.7 KiB

Hook-Based Guardrails

Hooks are Claude Code's most powerful security mechanism. Unlike static deny lists, hooks can run arbitrary logic to decide whether a tool call should proceed.

Pattern 1: Block dangerous commands

See hooks/pre-tool-use.sh for a working example. The core pattern:

# Read tool input from stdin
input=$(cat)
command=$(echo "$input" | python3 -c \
  "import sys,json; print(json.load(sys.stdin)['tool_input']['command'])")

# Check against blocked patterns
if echo "$command" | grep -qi "rm -rf /"; then
  echo '{"decision": "block", "reason": "Blocked: recursive delete at root"}'
  exit 2
fi

Pattern 2: Restrict file paths

Block writes outside the project directory:

file_path=$(echo "$input" | python3 -c \
  "import sys,json; print(json.load(sys.stdin)['tool_input']['file_path'])")

project_dir=$(pwd)
if [[ "$file_path" != "$project_dir"* ]]; then
  echo '{"decision": "block", "reason": "Blocked: write outside project"}'
  exit 2
fi

Pattern 3: Rate limiting

Prevent runaway API calls:

log_file="/tmp/claude-api-calls.log"
echo "$(date +%s)" >> "$log_file"

# Count calls in last 60 seconds
now=$(date +%s)
recent=$(awk -v now="$now" '$1 > now-60' "$log_file" | wc -l)

if [ "$recent" -gt 10 ]; then
  echo '{"decision": "block", "reason": "Rate limit: >10 calls/minute"}'
  exit 2
fi

Pattern 4: Audit trail with HTTP webhook

Send every tool call to an external logging service:

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "",
      "hooks": [{
        "type": "http",
        "url": "https://your-logging-service.com/audit",
        "headers": {
          "Authorization": "Bearer $AUDIT_TOKEN"
        }
      }]
    }]
  }
}

Pattern 5: Conditional approval

Block commands only in certain directories:

cwd=$(pwd)
if [[ "$cwd" == */production/* ]] && echo "$command" | grep -qi "deploy"; then
  echo '{"decision": "block", "reason": "Blocked: deploy from production dir"}'
  exit 2
fi

Comparison to OpenClaw security

OpenClaw uses container isolation (the agent runs inside Docker, so even if it tries to delete everything, the damage is contained). Claude Code uses permission layers (the agent is prevented from trying dangerous things in the first place).

Neither approach is strictly better:

  • Container isolation (OpenClaw): Handles unknown threats. If a new attack vector emerges, the container still limits damage.
  • Permission hooks (Claude Code): Handles known threats with precision. You can write exactly the rules you need. But you must anticipate the threat.

For personal use, hooks are more flexible and easier to customize. For enterprise/multi-tenant environments, container isolation provides stronger guarantees.