Project 18: “The Security Firewall Hook” — Security Governance

Attribute Value
File KIRO_CLI_LEARNING_PROJECTS.md
Main Programming Language Python or Rust
Coolness Level Level 4: Hardcore Tech Flex
Business Potential 3. Service & Support (Enterprise Security)
Difficulty Level 3: Advanced
Knowledge Area Security Governance

What you’ll build: A PreToolUse hook that blocks dangerous commands.

Why it teaches Governance: You enforce guardrails against hallucinated risk.

Success criteria:

  • A destructive command is blocked with a clear message.

Real World Outcome

You’ll have a security firewall that intercepts every Kiro tool call and blocks dangerous operations before execution. When Kiro attempts risky commands, your hook prevents disaster:

Blocked destructive command:

$ kiro "clean up the database by dropping all tables"

[PreToolUse Hook] Analyzing command...
🚫 BLOCKED: Dangerous Bash command detected

Command: DROP DATABASE production;
Reason: Database destructive operation (DROP, TRUNCATE)
Risk Level: CRITICAL
Suggested Alternative: Create a backup first with pg_dump

Hook Exit Code: 1 (Execution prevented)

Allowed safe command:

$ kiro "show me the database schema"

[PreToolUse Hook] Analyzing command...
✅ ALLOWED: Read-only database query

Command: \d+ users
Risk Level: LOW
Reason: SELECT queries are permitted

Security policy report:

$ python analyze-blocks.py

Security Firewall Report (Last 7 Days)
──────────────────────────────────────
Total Tool Calls: 1,247
Blocked: 23 (1.8%)
Allowed: 1,224 (98.2%)

Top Blocked Patterns:
1. rm -rf / (8 attempts)
2. DROP DATABASE (5 attempts)
3. chmod 777 (4 attempts)
4. curl | bash (3 attempts)
5. git push --force main (3 attempts)

Risk Prevented:
- Data loss: 13 incidents
- Security vulnerabilities: 7 incidents
- Production impact: 3 incidents

The hook runs pattern matching, AST analysis, and allow-list checking to catch both obvious and subtle threats before they execute.


The Core Question You’re Answering

“How do I prevent an AI agent from executing catastrophic commands while still allowing productive work?”

Before you start coding, consider: LLMs hallucinate. They suggest rm -rf / to “clean up space.” They recommend chmod 777 for “permission issues.” They propose DROP TABLE users to “fix schema conflicts.” A security firewall is your last line of defense against well-intentioned but devastating suggestions. This project teaches you to build guardrails that catch mistakes before they become disasters.


Concepts You Must Understand First

Stop and research these before coding:

  1. PreToolUse Hook Lifecycle
    • When does PreToolUse execute relative to tool invocation?
    • How does a non-zero exit code block tool execution?
    • Can you modify tool arguments in a PreToolUse hook?
    • What happens if the hook times out (5-second limit)?
    • Book Reference: Kiro CLI documentation - Hook System Architecture
  2. Command Pattern Matching
    • How do you distinguish rm -rf /tmp/safe from rm -rf /?
    • Should you use regex, AST parsing, or both?
    • How do you handle command aliases (ll, la, etc.)?
    • What about commands wrapped in functions or subshells?
    • Book Reference: “Compilers: Principles, Techniques, and Tools” by Aho et al. - Ch. 3 (Lexical Analysis)
  3. Bash AST Parsing
    • What is the structure of a Bash abstract syntax tree?
    • How do you extract the command name from complex pipelines?
    • How do you detect destructive flags (-f, --force, --no-preserve-root)?
    • Libraries: Python (bashlex), Rust (shell-words)
    • Book Reference: “The Linux Command Line” by William Shotts - Ch. 28 (Script Debugging)
  4. Security Policy Design
    • Deny-list (block known bad) vs allow-list (permit known good)?
    • How do you balance security with usability?
    • Should you allow overrides with explicit flags (–i-know-what-im-doing)?
    • How do you handle context-dependent risk (safe in dev, fatal in prod)?
    • Book Reference: “Building Secure and Reliable Systems” by Google - Ch. 6 (Design for Least Privilege)

Questions to Guide Your Design

Before implementing, think through these:

  1. Threat Model
    • What are the most dangerous commands to block (file deletion, permission changes, database drops)?
    • How do you detect SQL injection in commands?
    • Should you block network commands (curl, wget) if they download and execute?
    • What about indirect threats (cron jobs, systemd services)?
  2. Detection Strategy
    • Do you use regex patterns (fast but fragile) or AST parsing (slow but accurate)?
    • How do you handle obfuscated commands ($(echo cm)$(echo 64)echo cm64)?
    • Should you sandbox and execute the command in dry-run mode first?
    • Do you need a scoring system (low/medium/high risk) or binary allow/deny?
  3. User Experience
    • How do you communicate why a command was blocked?
    • Should you suggest safer alternatives?
    • Do you allow interactive approval (“This is risky, proceed? [y/N]”)?
    • How do you prevent alert fatigue from too many false positives?
  4. Policy Configuration
    • Should policies be global or per-project?
    • Do you support environment-specific rules (block in prod, allow in dev)?
    • How do you update patterns without modifying the hook code?
    • Should you support policy inheritance (base + overrides)?

Thinking Exercise

Manual Threat Detection Walkthrough

Before writing code, manually trace how your hook would analyze these commands:

Test Case 1: Obvious Threat

Command: rm -rf /

Analysis:

  • Command: rm (file deletion)
  • Flags: -rf (recursive, force)
  • Target: / (root directory)
  • Decision: BLOCK - Catastrophic data loss risk
  • Reason: Recursive deletion of root filesystem

Test Case 2: Subtle Threat

Command: find / -name "*.log" -exec rm {} \;

Analysis:

  • Command: find (search, seems harmless)
  • Execution: -exec rm (delete each match)
  • Target: / (all logs system-wide)
  • Decision: BLOCK - Hidden destructive operation in -exec
  • Reason: Mass file deletion disguised as search

Test Case 3: Context-Dependent

Command: chmod 777 /tmp/test.sh

Analysis:

  • Command: chmod (permission change)
  • Mode: 777 (world-writable)
  • Target: /tmp/test.sh (temp file)
  • Decision: WARN - Bad practice but low immediate risk
  • Reason: Insecure permissions on non-critical file

Test Case 4: SQL Injection

Command: psql -c "DROP TABLE users WHERE id = 1; DROP DATABASE production; --"

Analysis:

  • Command: psql (database client)
  • SQL: Multiple statements detected
  • Keywords: DROP TABLE, DROP DATABASE
  • Decision: BLOCK - SQL injection attempt
  • Reason: Destructive SQL operations

Questions while analyzing:

  • Which patterns can you detect with regex alone?
  • Which require parsing the command structure?
  • How would you handle base64-encoded commands?
  • What if the command is split across multiple tool calls?

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “How would you detect a destructive command hidden in a base64-encoded string that’s later decoded and executed?”
  2. “Explain the difference between deny-list and allow-list security models. Which is appropriate for AI agent governance?”
  3. “How do you prevent time-of-check to time-of-use (TOCTOU) attacks where the command changes after your hook approves it?”
  4. “What strategies would you use to minimize false positives while maintaining strong security boundaries?”
  5. “How would you design a policy system that’s secure by default but allows power users to override when necessary?”
  6. “Explain how you would parse a complex Bash command with pipes, redirects, and subshells to extract all executable components.”

Hints in Layers

Hint 1: Start with Pattern Matching Begin with a deny-list of obvious threats using regex:

  • rm -rf /
  • DROP DATABASE
  • chmod 777
  • curl .* | bash Build incrementally from simple patterns to complex AST analysis.

Hint 2: Parse the Bash Command Structure Use a library like bashlex (Python) to parse commands into an AST. Walk the tree to extract:

  • Primary command name
  • All flags and arguments
  • Nested commands in subshells or backticks This catches threats hidden in complex syntax.

Hint 3: Risk Scoring System Assign risk scores to each pattern:

  • Critical (100): rm -rf /, DROP DATABASE
  • High (75): chmod 777, git push --force main
  • Medium (50): Unverified curl downloads
  • Low (25): Warnings only Block anything ≥75, warn for 25-74.

Hint 4: Configuration-Driven Policies Load patterns from a YAML config file:

critical_patterns:
  - pattern: 'rm\s+-rf\s+/'
    reason: "Root filesystem deletion"
  - pattern: 'DROP\s+DATABASE'
    reason: "Database destruction"

This allows updates without code changes.


Books That Will Help

Topic Book Chapter
Security Policy Design “Building Secure and Reliable Systems” by Google Ch. 6 (Design for Least Privilege), Ch. 12 (Crisis Management)
Command Parsing “Compilers: Principles, Techniques, and Tools” by Aho et al. Ch. 3 (Lexical Analysis), Ch. 4 (Syntax Analysis)
Bash Scripting Security “The Linux Command Line” by William Shotts Ch. 28 (Script Debugging), Ch. 29 (Flow Control)
Pattern Matching “Regular Expressions Cookbook” by Goyvaerts & Levithan Ch. 4 (Validation), Ch. 7 (Security)
Hook System Kiro CLI docs Hooks System, Security Best Practices

Common Pitfalls & Debugging

Problem 1: “Hook blocks legitimate commands (false positives)”

  • Why: Overly broad regex patterns match harmless variations
  • Fix: Test patterns against a suite of safe commands:
    # Safe: rm -rf ./temp
    # Unsafe: rm -rf /
    # Pattern should distinguish based on target path
    
  • Quick test: Create a test suite with 100 safe and 20 unsafe commands

Problem 2: “Obfuscated commands bypass detection”

  • Why: Regex can’t detect $(echo rm) -rf /
  • Fix: Execute the command in a sandbox with dry-run mode:
    bash -n -c "$command" 2>&1  # Check syntax without executing
    
  • Quick test: Try variations like r''m -rf, ${CMD}, base64 encoding

Problem 3: “Hook is too slow, Kiro times out”

  • Why: AST parsing is expensive for every command
  • Fix: Implement a fast-path for common safe commands:
    if command.startswith(('ls', 'cat', 'grep', 'echo')):
        return ALLOW  # Skip expensive parsing
    
  • Quick test: Time hook execution—should be <100ms for 95% of commands

Problem 4: “Policy updates require redeploying the hook”

  • Why: Patterns are hardcoded in the script
  • Fix: Load patterns from ~/.kiro/security-policy.yaml:
    with open(os.path.expanduser('~/.kiro/security-policy.yaml')) as f:
        policy = yaml.safe_load(f)
    
  • Quick test: Modify YAML file, verify new patterns apply without restart

Problem 5: “Can’t block SQL injection in psql commands”

  • Why: SQL is embedded as a string argument
  • Fix: Parse SQL with a library like sqlparse (Python):
    import sqlparse
    statements = sqlparse.split(sql_query)
    for stmt in statements:
        if 'DROP' in stmt.upper() or 'DELETE' in stmt.upper():
            return BLOCK
    
  • Quick test: Test with various SQL injection payloads

Definition of Done

  • Hook intercepts all PreToolUse events for Bash and Edit tools
  • Critical patterns (rm -rf /, DROP DATABASE, chmod 777) are blocked
  • Blocked commands log to ~/.kiro/security-log.jsonl with reason
  • AST parsing catches threats hidden in complex command structures
  • Policy is loaded from YAML config file, updatable without code changes
  • False positive rate is <2% on a benchmark of 500 real commands
  • Hook completes analysis in <100ms for 95th percentile
  • Blocked commands show helpful error messages with alternatives
  • Allow-list overrides are supported via –security-override flag
  • Environment-specific policies (dev vs prod) are configurable
  • Documentation explains how to add custom patterns and policies