Skip to content

Security Hooks

This document details the security hooks that protect Project Aegis from dangerous operations.

Overview

Aegis uses Claude Code's hook system to intercept and validate operations before they execute. Hooks are configured in ~/.claude/settings.json and execute as Python or Bash scripts.

Hook Configuration

Location: ~/.claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "/home/agent/.claude/hooks/block-sensitive-files.py",
            "timeout": 5
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/home/agent/.claude/hooks/bash-validator.py",
            "timeout": 5
          }
        ]
      },
      {
        "matcher": "mcp__",
        "hooks": [
          {
            "type": "command",
            "command": "/home/agent/.claude/hooks/mcp-param-validator.py",
            "timeout": 5
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "mcp__",
        "hooks": [
          {
            "type": "command",
            "command": "/home/agent/.claude/hooks/mcp-security-audit.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

Hook Types

PreToolUse

Executes before a tool runs. Exit codes determine behavior:

  • 0: Allow operation
  • 1: Non-blocking error (log and continue)
  • 2: Block operation (prevents execution)

PostToolUse

Executes after a tool runs. Used for logging and auditing (cannot block).

Hook Events

Event When It Fires Use Cases
PreToolUse Before tool execution Validation, blocking dangerous operations
PostToolUse After tool execution Audit logging, cost tracking
SessionStart When Claude Code starts Load tasks, check system state
Stop When Claude Code stops Quality gates, autonomous mode
Notification On system notifications Forward alerts to Discord/Telegram
PermissionRequest On permission dialogs Auto-approve trusted operations

Security Hooks in Detail

1. block-sensitive-files.py

Purpose: Prevent modification of credentials, secrets, and critical system files.

Hook Type: PreToolUse (Write, Edit)

Location: /home/agent/.claude/hooks/block-sensitive-files.py

Protected Patterns (BLOCK)

Operations on these files are blocked (exit code 2):

PROTECTED_PATTERNS = [
    r'\.pem$',                  # SSL certificates
    r'\.key$',                  # Private keys
    r'id_rsa',                  # SSH RSA keys
    r'id_ed25519',              # SSH Ed25519 keys
    r'/\.git/',                 # Git internals
    r'package-lock\.json$',     # Lock files
    r'yarn\.lock$',
    r'poetry\.lock$',
]

Example Blocked Operation:

Tool: Edit
File: ~/.ssh/id_ed25519
Result: BLOCKED with error message

Caution Patterns (WARN)

Operations on these files are allowed but warned:

CAUTION_PATTERNS = [
    r'\.env$',                  # Environment files
    r'\.env\.',                 # .env.production, etc.
    r'/\.secure/',              # Credentials directory
    r'credentials',             # Any credentials file
    r'settings\.json$',         # Claude settings
    r'config\.json$',           # Config files
    r'docker-compose.*\.yml$',  # Docker Compose files
    r'\.claude\.json$',         # MCP config
]

Example Warning:

Tool: Edit
File: ~/.secure/.env
Result: ALLOWED with warning "CAUTION: Modifying sensitive config: /home/agent/.secure/.env"

Use Cases

  • Prevent accidental credential exposure
  • Block editing of SSH keys
  • Protect Git internals from corruption
  • Allow intentional .env editing (with warnings)

2. bash-validator.py

Purpose: Block potentially destructive Bash commands.

Hook Type: PreToolUse (Bash)

Location: /home/agent/.claude/hooks/bash-validator.py

Dangerous Patterns (BLOCK)

DANGEROUS_PATTERNS = [
    (r'\brm\s+-rf\s+/', 'rm -rf on root path'),
    (r'\brm\s+-rf\s+~', 'rm -rf on home directory'),
    (r'\brm\s+-rf\s+\*', 'rm -rf with wildcard'),
    (r'\bsudo\s+rm\s+-rf', 'sudo rm -rf'),
    (r'\bchmod\s+777', 'overly permissive chmod 777'),
    (r'\bmkfs\.', 'filesystem formatting'),
    (r'\bdd\s+.*of=/dev/', 'dd to device'),
    (r':(){.*};:', 'fork bomb pattern'),
    (r'\beval\s+.*\$', 'eval with variable expansion'),
    (r'>\s*/etc/', 'redirect to /etc'),
    (r'\bgit\s+push\s+.*--force\s+.*main', 'force push to main'),
    (r'\bgit\s+push\s+.*--force\s+.*master', 'force push to master'),
    (r'\bgit\s+reset\s+--hard\s+origin', 'hard reset to origin'),
]

Example Blocked Operations:

# Blocked
rm -rf /var/log/*
chmod 777 ~/.ssh/id_ed25519
git push --force origin main
dd if=/dev/zero of=/dev/sda

# Error message
BLOCKED: Dangerous command detected - rm -rf on root path
Command: rm -rf /var/log/*

Suspicious Patterns (WARN)

SUSPICIOUS_PATTERNS = [
    (r'\bcurl\s+.*\|\s*bash', 'piping curl to bash'),
    (r'\bwget\s+.*\|\s*bash', 'piping wget to bash'),
    (r'\bnohup\s+', 'nohup background process'),
    (r'&\s*$', 'backgrounding command'),
]

Example Warnings:

# Allowed with warning
curl https://install.sh | bash

# Warning message
NOTICE: Suspicious command - piping curl to bash

Use Cases

  • Prevent accidental data loss (rm -rf)
  • Block overly permissive permissions (chmod 777)
  • Prevent destructive Git operations (force push to main)
  • Warn on potentially dangerous patterns (curl | bash)

3. mcp-param-validator.py

Purpose: Validate MCP tool parameters before execution.

Hook Type: PreToolUse (mcp__)

Location: /home/agent/.claude/hooks/mcp-param-validator.py

Validation Rules

  • Required parameters: Ensure present
  • Type validation: String/number/boolean checks
  • Path traversal: Block ../ in file paths
  • SQL injection: Block suspicious SQL patterns in queries
  • Command injection: Block shell metacharacters in commands

Example Validations:

# Block path traversal
mcp__filesystem__read_file(path="/home/agent/../../etc/passwd")
# Result: BLOCKED

# Block SQL injection attempt
mcp__postgres__execute(query="SELECT * FROM users WHERE id='1' OR '1'='1'")
# Result: BLOCKED

# Allow normal operation
mcp__filesystem__read_file(path="/home/agent/memory/journal/2026-01-25.md")
# Result: ALLOWED

Use Cases

  • Prevent path traversal attacks
  • Block SQL injection attempts
  • Validate required MCP parameters
  • Ensure type safety

4. mcp-security-audit.py

Purpose: Log all MCP tool usage with risk-based flagging.

Hook Type: PostToolUse (mcp__)

Location: /home/agent/.claude/hooks/mcp-security-audit.py

Risk Levels

MCP_RISK_LEVELS = {
    # HIGH RISK - Can execute code or access sensitive resources
    'docker': 'high',
    'postgres': 'high',
    'filesystem': 'high',
    'stackwiz': 'high',

    # MEDIUM RISK - External API access, potential data exfiltration
    'github': 'medium',
    'google-workspace': 'medium',
    'discord': 'medium',
    'telegram': 'medium',
    'vonage': 'medium',

    # LOW RISK - Read-only or sandboxed
    'memory': 'low',
    'ollama': 'low',
    'playwright': 'low',
    'wallet': 'low',
}

Flagged Operations

High-risk operations that are always logged with full context:

HIGH_RISK_OPERATIONS = {
    'docker': ['remove_container', 'remove_image', 'remove_volume', 'remove_network'],
    'postgres': ['execute'],  # DML operations
    'filesystem': ['write_file', 'edit_file', 'move_file'],
    'github': ['push_files', 'create_or_update_file', 'merge_pull_request'],
    'stackwiz': ['manage_stack'],  # Can remove stacks
}

Audit Log Format

Location: ~/memory/security/mcp-audit.jsonl

{
  "timestamp": "2026-01-25T12:00:00Z",
  "session_id": "abc123",
  "mcp_server": "docker",
  "operation": "remove_container",
  "risk_level": "high",
  "flagged": true,
  "event": "PostToolUse",
  "input_summary": {
    "container_id": "aegis-dashboard",
    "force": true
  }
}

Sensitive Data Redaction

# Fields that are always redacted
SENSITIVE_FIELDS = ['password', 'token', 'secret', 'key', 'credential']

# Long values are truncated
if len(value) > 200:
    sanitized_input[key] = value[:200] + '...[truncated]'

Use Cases

  • Security forensics (who did what, when)
  • Anomaly detection (unusual MCP usage patterns)
  • Compliance auditing (SOC 2, GDPR)
  • Cost tracking (expensive operations)

Querying Audit Logs

# Find all flagged operations
jq 'select(.flagged == true)' ~/memory/security/mcp-audit.jsonl

# Find all high-risk operations
jq 'select(.risk_level == "high")' ~/memory/security/mcp-audit.jsonl

# Find operations by session
jq 'select(.session_id == "abc123")' ~/memory/security/mcp-audit.jsonl | tail -20

# Find operations in last hour
jq --arg time "$(date -u -d '1 hour ago' --iso-8601=seconds)" \
  'select(.timestamp > $time)' ~/memory/security/mcp-audit.jsonl

Additional Hooks (Non-Security)

cost-tracker.sh

Purpose: Log tool usage for cost analysis.

Hook Type: PostToolUse (all tools)

Location: /home/agent/.claude/hooks/cost-tracker.sh

Output: ~/memory/tool-usage.jsonl

episodic-recorder.py

Purpose: Record significant operations to episodic memory.

Hook Type: PostToolUse (Task, WebSearch, Bash, Edit, Write, MCP)

Location: /home/agent/.claude/hooks/episodic-recorder.py

Output: ~/memory/episodic/ (JSONL files by date)

session-init.sh

Purpose: Initialize session (load Beads tasks, check autonomous mode).

Hook Type: SessionStart

Location: /home/agent/.claude/hooks/session-init.sh

quality-gate.sh

Purpose: Session hygiene checks (uncommitted changes, empty journal, open tasks).

Hook Type: Stop

Location: /home/agent/.claude/hooks/quality-gate.sh

autonomous-continue.sh

Purpose: Auto-continue Claude Code during autonomous mode.

Hook Type: Stop

Location: /home/agent/.claude/hooks/autonomous-continue.sh

Hook Development Best Practices

Exit Codes

import sys

sys.exit(0)  # Allow operation
sys.exit(1)  # Non-blocking error (log and continue)
sys.exit(2)  # Block operation (prevent execution)

Input Format

Hooks receive JSON via stdin:

import json
import sys

data = json.load(sys.stdin)
tool_name = data.get('tool_name', '')
tool_input = data.get('tool_input', {})
session_id = data.get('session_id', 'unknown')
hook_event = data.get('hook_event_name', 'unknown')

Error Handling

try:
    # Hook logic
    sys.exit(0)
except Exception as e:
    print(f"Hook error: {e}", file=sys.stderr)
    sys.exit(1)  # Non-blocking error

Logging

Always log to stderr for visibility:

print(f"BLOCKED: Reason for blocking", file=sys.stderr)
print(f"CAUTION: Warning message", file=sys.stderr)

Performance

  • Keep hooks fast (<100ms)
  • Use regex for pattern matching
  • Avoid network calls
  • Cache expensive operations

Testing

# Test a hook manually
echo '{"tool_name": "Write", "tool_input": {"file_path": "/home/agent/.ssh/id_rsa"}}' | \
  /home/agent/.claude/hooks/block-sensitive-files.py

# Check exit code
echo $?  # 2 = blocked, 0 = allowed

Security Hook Maintenance

Adding New Protected Files

Edit block-sensitive-files.py:

PROTECTED_PATTERNS = [
    r'\.pem$',
    r'\.key$',
    r'id_rsa',
    r'id_ed25519',
    r'/\.git/',
    r'new_pattern',  # Add here
]

Adding New Dangerous Commands

Edit bash-validator.py:

DANGEROUS_PATTERNS = [
    (r'\brm\s+-rf\s+/', 'rm -rf on root path'),
    (r'\bnew_pattern', 'description'),  # Add here
]

Adjusting MCP Risk Levels

Edit mcp-security-audit.py:

MCP_RISK_LEVELS = {
    'docker': 'high',
    'new-server': 'medium',  # Add new servers here
}

HIGH_RISK_OPERATIONS = {
    'docker': ['remove_container'],
    'new-server': ['dangerous_operation'],  # Add flagged ops here
}

Bypassing Hooks (Emergency)

WARNING: Only bypass hooks in emergency situations.

Temporary Bypass

  1. Stop Claude Code
  2. Edit ~/.claude/settings.json
  3. Comment out the hook:
    "PreToolUse": [
      // {
      //   "matcher": "Bash",
      //   "hooks": [...]
      // }
    ]
    
  4. Restart Claude Code
  5. REMEMBER TO RE-ENABLE AFTER
# Disable hook by renaming
mv /home/agent/.claude/hooks/bash-validator.py \
   /home/agent/.claude/hooks/bash-validator.py.disabled

Monitoring and Alerts

Daily Hook Reports

# Count blocked operations today
jq 'select(.timestamp | startswith("2026-01-25"))' \
  ~/memory/security/mcp-audit.jsonl | wc -l

# Find most-used MCP servers
jq -r '.mcp_server' ~/memory/security/mcp-audit.jsonl | sort | uniq -c | sort -nr

Alert on Suspicious Activity

Create a cron job to alert on flagged operations:

# /home/agent/.claude/hooks/alert-on-flagged.sh
#!/bin/bash
FLAGGED=$(jq 'select(.flagged == true and .timestamp > (now - 3600 | todate))' \
  ~/memory/security/mcp-audit.jsonl | wc -l)

if [ "$FLAGGED" -gt 5 ]; then
  # Post to Discord #alerts
  curl -X POST https://aegisagent.ai/api/discord/alert \
    -d "text=WARNING: $FLAGGED flagged MCP operations in last hour"
fi

Compliance and Auditing

SOC 2 Controls

Control Hook Implementation
Access Logging mcp-security-audit.py logs all MCP access
Least Privilege MCP risk levels enforce (high/medium/low)
Change Management episodic-recorder.py logs all Write/Edit operations
Dangerous Operations bash-validator.py blocks destructive commands

GDPR Controls

Requirement Hook Implementation
Data Access Logs mcp-audit.jsonl provides trail
Data Deletion Log requests via mcp-security-audit.py
Consent Management (Not implemented - manual process)

Audit Report Generation

# Generate monthly security report
cat <<EOF > ~/memory/security/report-2026-01.md
# Security Report - January 2026

## Summary
- Total MCP operations: $(jq -s 'length' ~/memory/security/mcp-audit.jsonl)
- Flagged operations: $(jq -s 'map(select(.flagged == true)) | length' ~/memory/security/mcp-audit.jsonl)
- Blocked bash commands: $(grep -c "BLOCKED" ~/.claude/hooks/*.log 2>/dev/null || echo 0)

## Top MCP Servers
$(jq -r '.mcp_server' ~/memory/security/mcp-audit.jsonl | sort | uniq -c | sort -nr | head -5)

## Flagged Operations
$(jq 'select(.flagged == true)' ~/memory/security/mcp-audit.jsonl | head -10)
EOF

Troubleshooting

Hook Not Firing

  1. Check ~/.claude/settings.json syntax
  2. Verify hook script has execute permissions:
    chmod +x /home/agent/.claude/hooks/*.py
    chmod +x /home/agent/.claude/hooks/*.sh
    
  3. Test hook manually with sample input
  4. Check Claude Code logs: ~/.claude/logs/

Hook Timing Out

  • Increase timeout in settings.json:
    "timeout": 10  // Increase from 5 to 10 seconds
    
  • Optimize hook script (remove slow operations)

Hook Producing Wrong Result

  • Test with verbose logging:
    import sys
    print(f"DEBUG: tool_name={tool_name}", file=sys.stderr)
    print(f"DEBUG: tool_input={tool_input}", file=sys.stderr)
    
  • Check exit code behavior (0/1/2)

Future Enhancements

Planned (v2.0)

  • Machine learning anomaly detection on MCP audit logs
  • Real-time alerting to Discord/Telegram on flagged operations
  • Rate limiting for expensive MCP operations
  • Approval workflow for high-risk operations (human-in-the-loop)
  • Compliance report generation (SOC 2, GDPR, ISO 27001)
  • Integration with external SIEM (Splunk, Datadog)

Under Consideration

  • Encrypted audit logs (GPG)
  • Multi-user support with per-user MCP access control
  • Automated incident response (e.g., revoke API keys on suspicious activity)
  • Hook A/B testing framework (gradual rollout of new hooks)