claude-hooks/docs/how-to/customize-patterns.md

5.8 KiB

How to Add Custom Command Validation Patterns

When to use this guide: You want to block specific commands or add warnings for commands that are problematic in your environment.

Add a Dangerous Command Pattern

If you have commands that should never be run in your environment:

  1. Edit the command validator:

    nano hooks/command-validator.js
    
  2. Find the dangerousPatterns array (around line 23):

    this.dangerousPatterns = [
        /rm\s+-rf\s+\//,           // Delete root
        /mkfs\./,                  // Format filesystem  
        // Add your pattern here
    ];
    
  3. Add your pattern:

    this.dangerousPatterns = [
        /rm\s+-rf\s+\//,           // Delete root
        /mkfs\./,                  // Format filesystem
        /docker\s+system\s+prune\s+--all/,  // Delete all Docker data
        /kubectl\s+delete\s+namespace\s+production/,  // Delete prod namespace
    ];
    
  4. Test your pattern:

    echo '{"tool": "Bash", "parameters": {"command": "docker system prune --all"}}' | node hooks/command-validator.js
    

    Should return: {"allow": false, "message": "⛔ Command blocked: Dangerous command pattern detected"}

Add Warning Patterns

For commands that are risky but sometimes legitimate:

  1. Find the suspiciousPatterns array:

    this.suspiciousPatterns = [
        /sudo\s+rm/,              // Sudo with rm
        /chmod\s+777/,            // Overly permissive
        // Add your pattern here
    ];
    
  2. Add patterns that should warn but not block:

    this.suspiciousPatterns = [
        /sudo\s+rm/,              // Sudo with rm
        /chmod\s+777/,            // Overly permissive
        /npm\s+install\s+.*--global/,  // Global npm installs
        /pip\s+install.*--user/,       // User pip installs
    ];
    

Customize for Your Tech Stack

For Docker Environments

Add Docker-specific protections:

// In dangerousPatterns:
/docker\s+rm\s+.*-f.*/,      // Force remove containers
/docker\s+rmi\s+.*-f.*/,     // Force remove images

// In suspiciousPatterns:  
/docker\s+run.*--privileged/,  // Privileged containers
/docker.*-v\s+\/:\/.*/, // Mount root filesystem

For Kubernetes

Protect production namespaces:

// In dangerousPatterns:
/kubectl\s+delete\s+.*production.*/,
/kubectl\s+delete\s+.*prod.*/,
/helm\s+delete\s+.*production.*/,

// In suspiciousPatterns:
/kubectl\s+apply.*production.*/,
/kubectl.*--all-namespaces.*delete/,

For Database Operations

Prevent destructive database commands:

// In dangerousPatterns:
/DROP\s+DATABASE.*/i,
/TRUNCATE\s+TABLE.*/i,
/DELETE\s+FROM.*WHERE\s+1=1/i,

// In suspiciousPatterns:
/UPDATE.*SET.*WHERE\s+1=1/i,
/ALTER\s+TABLE.*DROP.*/i,

Environment-Specific Patterns

For Production Servers

// In dangerousPatterns:
/systemctl\s+stop\s+(nginx|apache|mysql)/,
/service\s+(nginx|apache|mysql)\s+stop/,
/killall\s+-9.*/,

// In suspiciousPatterns:
/sudo\s+systemctl\s+restart.*/,
/sudo\s+service.*restart.*/,

For Development Machines

// In suspiciousPatterns:
/rm\s+-rf\s+node_modules/,    // Can break local dev
/git\s+reset\s+--hard\s+HEAD~[0-9]+/,  // Lose multiple commits
/git\s+push\s+.*--force.*/,   // Force push

Test Your Custom Patterns

Create a test script to verify your patterns work:

cat > test_patterns.sh << 'EOF'
#!/bin/bash

# Test dangerous pattern (should block)
echo "Testing dangerous pattern..."
echo '{"tool": "Bash", "parameters": {"command": "docker system prune --all"}}' | node hooks/command-validator.js

# Test suspicious pattern (should warn)  
echo "Testing suspicious pattern..."
echo '{"tool": "Bash", "parameters": {"command": "npm install -g dangerous-package"}}' | node hooks/command-validator.js

# Test normal command (should pass)
echo "Testing normal command..."
echo '{"tool": "Bash", "parameters": {"command": "ls -la"}}' | node hooks/command-validator.js
EOF

chmod +x test_patterns.sh
./test_patterns.sh

Advanced: Context-Aware Patterns

For patterns that depend on file context:

  1. Edit the validation function to check current directory or files:
    validateCommandSafety(command) {
        // Your existing patterns...
    
        // Context-aware validation
        if (command.toLowerCase().includes("git push")) {
            // Check if we're in a production branch
            try {
                const { execSync } = require('child_process');
                const currentBranch = execSync('git branch --show-current', 
                    { encoding: 'utf8' }).trim();
                if (['main', 'master', 'production'].includes(currentBranch)) {
                    return {
                        allowed: true,
                        reason: "⚠️ Pushing to protected branch",
                        severity: "warning"
                    };
                }
            } catch {
                // Ignore errors
            }
        }
    }
    

Pattern Syntax Reference

Use JavaScript regex patterns:

  • \s+ - One or more whitespace characters
  • .* - Any characters (greedy)
  • .*? - Any characters (non-greedy)
  • [0-9]+ - One or more digits
  • (option1|option2) - Either option1 or option2
  • ^ - Start of string
  • $ - End of string
  • i flag - Case insensitive matching

Examples:

  • /rm\s+-rf\s+\// - Matches "rm -rf /"
  • /git\s+push.*--force/ - Matches "git push" followed by "--force" anywhere
  • /^sudo\s+/ - Matches commands starting with "sudo"

Reload Changes

After modifying patterns:

  1. Test the changes:

    ./test_patterns.sh
    
  2. No restart needed - changes take effect immediately since hooks are called fresh each time

  3. Verify in Claude by trying a command that should trigger your new pattern