Destructive Command Guard (dcg)

repository·main·Indexed 26 days ago

https://github.com/dicklesworthstone/destructive_command_guard

A high-performance hook and GitHub Action designed to protect developers from AI coding agents (such as Claude Code, Copilot, or Cursor) by blocking catastrophic commands like `rm -rf` or `git reset --hard`. It features a modular pack system for technology-specific protections (databases, cloud, containers), agent-specific security profiles, and support for scanning shell scripts, Dockerfiles, and CI configurations.

Tokens
127.2K
Snippets
301
Records
603
Agent score
90%

What's inside destructive_command_guard

  1. Understand the Makefile Extractor v1 behavior

    main

    The dcg scan Makefile extractor (ID: makefile.recipe) analyzes recipe lines in Makefiles to extract executable commands for security scanning. It follows a conservative approach, preferring silence over false positives.

    Key behavior rules:

    • File Detection: It only matches files named Makefile, makefile, or MAKEFILE (case-insensitive). It does not support .mk include files, GNUmakefile, makefile.in, or Makefile.am.
    • Recipe Identification: Only lines starting with a literal TAB character are treated as recipe lines containing shell commands.
    • Variable Handling: The v1 extractor does NOT expand variables. It extracts literal syntax like $(VAR), ${VAR}, or $$HOME. This means dangerous commands hidden behind variables will not be detected.
    • Extraction Scope: It extracts commands from recipe lines but ignores variable assignments, target definitions, directives (like .PHONY), and conditionals (like ifeq).
  2. Understand the Lazy Pack Registry Design

    main

    The Lazy Pack Registry is a design pattern used in destructive_command_guard to eliminate eager regex compilation during startup. Instead of compiling all regular expressions when the registry is initialized, the system uses metadata-only specifications (PackSpec, SafePatternSpec, DestructivePatternSpec) and compiles regexes only when a pattern is actually evaluated for a command match. This preserves behavior, ordering, and attribution while improving performance on the hot path.

    Key Evaluation Logic:

    1. Safe pass: Iterates safe patterns across enabled packs; returns 'allow' on the first match.
    2. Destructive pass: Iterates destructive patterns across enabled packs; returns the first match (respecting severity/mode).

    Compilation is handled via std::sync::OnceLock, ensuring OnceLock::get_or_init is called only on the first match attempt.

  3. Understand the Execution Context Layer and False Positive Immunity

    main

    The Execution Context Layer distinguishes between bytes that are executed code versus bytes that are merely data (strings, comments, documentation). This prevents the guard from blocking commands when a dangerous substring appears in a non-executable context, such as a git commit message or a search pattern.

    There are two primary mechanisms for this:

    1. Safe String-Argument Registry: A curated list of commands where specific flags are known to contain data rather than code.
    2. Execution-Context Tokenizer: A shell tokenizer that classifies command segments into SpanKind categories to determine if they should be subject to pattern matching.
  4. Understand the Destructive Command Guard (dcg) Architecture

    main

    When used as a PreToolUse hook (e.g., with Claude Code), dcg follows this execution flow:

    1. Parse Input: Reads the Claude hook protocol via stdin (JSON format).
    2. Command Extraction: Extracts the Bash command string from the JSON.
    3. Normalization: Normalizes the command (e.g., stripping absolute paths like /usr/bin/git to just git).
    4. Keyword Gating: Performs a quick check against keywords to skip expensive regex work for irrelevant commands.
    5. Whitelist Check: Checks against safe patterns (whitelist) before checking destructive patterns.
    6. Blacklist Check: Evaluates destructive patterns (blacklist).
    7. Default Action: If no patterns match, the command is allowed by default.
    8. Denial Output: If a command is denied, dcg outputs a colorful warning to stderr and a JSON denial message to stdout.

    The system uses a modular pack system where packs (covering git, filesystem, database, containers, etc.) can be enabled or disabled via configuration. Each pack includes keywords to optimize performance via quick rejection.

  5. Understand the dcg Architecture and Workflow

    main

    The Destructive Command Guard (dcg) acts as a middleware hook for AI agents (Claude, Codex, Gemini, Copilot, Cursor, Hermes). It intercepts command execution requests via a PreToolUse hook using JSON via stdin.

    Workflow:

    1. Parse & Normalize: The incoming JSON is parsed and the command is normalized.
    2. Quick Reject: A fast filter eliminates most safe commands immediately.
    3. Pattern Matching:
      • Check SAFE_PATTERNS (whitelist): If a match is found, the command is ALLOWED.
      • Check DESTRUCTIVE_PATTERNS (blacklist): If a match is found, the command is DENIED.
      • No match: The command is ALLOWED by default.
    4. Output:
      • Allowed: Returns an empty JSON object to stdout.
      • Denied: Returns a JSON deny object to stdout and provides a rich human-readable reason to stderr.
  6. Understand Tiered Heredoc & Inline Script Scanning

    main

    To prevent agents from hiding destructive commands inside heredocs, inline scripts, or piped interpreters, DCG uses a three-tier detection architecture. This ensures high performance for common commands while providing deep structural analysis for suspicious ones.

    1. Tier 1: Ultra-Fast Trigger Detection: Uses fast regex to identify if a command contains triggers like heredoc operators (<<), inline flags (-c, -e, -r), or pipes to interpreters. If no trigger is found, the command is allowed immediately.
    2. Tier 2: Bounded Extraction: If a trigger is found, the system extracts the body of the heredoc or the inline script string. This process is strictly bounded by size, line count, and time limits to prevent DoS attacks.
    3. Tier 3: AST-Aware Matching: The extracted content is parsed using AST (Abstract Syntax Tree) tools like ast-grep or tree-sitter. This allows the system to match language-specific destructive patterns (e.g., os.system in Python) structurally rather than relying on simple substring matching.
  7. Architecture Overview: rich_rust Integration for dcg

    main

    The integration of rich_rust into dcg aims to provide premium, stylish terminal output for human observers via stderr, while ensuring that agent-facing output (JSON on stdout) remains completely untouched and compatible with AI coding agents.

    Output Routing Strategy

    • STDOUT: Reserved exclusively for pure JSON output intended for AI agents.
    • STDERR: Used for all human-facing, colorful, and styled terminal output (Panels, Tables, Rules, Progress Bars).
  8. Understand the Interactive Mode Security Model

    main

    The Interactive Mode is designed to prevent AI agents from bypassing command guards by requiring human-verifiable interaction. The security model relies on several core implementation requirements to ensure that an automated agent cannot simulate a human response.

    Key security pillars include:

    • TTY Detection: The system must detect if stdin is a TTY. If it is not a TTY (e.g., a piped input or a non-interactive shell), the command is immediately blocked to prevent automated bypass.
    • Verification Challenges: The system uses interactive challenges such as random verification codes, timeouts, or semantic verification to ensure a human is present.
    • Audit Logging: All interactive bypass attempts (both successful and failed) are logged with the timestamp, command, a hash of the code used, the result, and TTY information to detect automated attack patterns.
  9. DCG Design Principles

    main

    The development and usage of DCG are guided by these core principles:

    • Stability (P0): Never hang, crash, or spike unpredictably. Maximum command processing time is capped at 10ms. The tool must fail-open on timeouts or parse errors.
    • Safety (P1): Default to allowing unknown or ambiguous commands. Only deny high-confidence catastrophic commands with clear explanations.
    • Determinism (P2): Ensure the same input always produces the same decision and attribution. Use stable pack ordering and provide decision traces via dcg explain.
    • Precision (P3): Treat false positives as a primary concern. Use context-aware detection (distinguishing between executed commands and data) and allowlisting by rule ID.
    • Incremental Delivery (P4): Prioritize correctness and false-positive reduction before adding deeper scanning or UX features.
  10. Understand dcg limitations on Windows

    main

    Be aware of the following operational boundaries on Windows:

    • Scope of Protection: dcg evaluates shell commands exposed by an agent's hook. It does not intercept Task Scheduler, Windows services, separate human terminals, or network calls made by an already-running process.
    • Codex unified_exec: Codex's PreToolUse hooks do not intercept the unified_exec shell path used by Codex Desktop / codex exec on Windows. Commands routed this way are not blocked.
    • Runtime-built Commands: dcg inspects static payloads (like cmd /c, call, if, start, for ... do) and decodes caret syntax. However, it cannot intercept commands synthesized via %VAR% or delayed !VAR! expansion that occur after the hook returns. For these, use network egress controls.
    • History DB: The SQLite history DB is best-effort. Under extreme concurrent-process contention, some decision records may not be written to ensure the security hook never blocks or breaks. The block/allow decision itself remains correct.
  11. Understand dcg Response Levels

    main

    The Destructive Command Guard (dcg) uses a graduated response system to handle destructive commands based on frequency and severity. There are three primary response levels:

    • WARNING: The command is allowed to proceed. A warning is displayed to stderr and the event is logged. This is typically used for the first occurrence in a session.
    • SOFT_BLOCK: The command is blocked initially. In interactive mode, the user can confirm to proceed by using the dcg confirm <code> command. This is triggered when a session threshold is exceeded.
    • HARD_BLOCK: The command is blocked with no override. The user must either add the pattern to an allowlist or use dcg allow-once <code>. This is triggered when a history threshold is exceeded or when using paranoid mode.
  12. Review dcg Security Limitations

    main

    dcg is designed for well-intentioned but fallible AI agents. It is not a security tool against malicious actors.

    Key Limitations:

    • Malicious Actors: A determined attacker can bypass the hook.
    • Non-Bash Commands: Direct file writes via Python, JavaScript, or API calls are not intercepted.
    • Scripts: dcg does not inspect the contents of scripts (e.g., ./deploy.sh).
    • Committed Work: It cannot prevent the loss of local-only commits.
    • Dynamic stdin: dcg traces bounded literal pipelines (like echo | ...) into REPLs (e.g., psql, mysql, sqlite3). However, it fails closed (blocks) on unknown/dynamic producers, non-UTF-8 files, or payloads exceeding 256 KiB to prevent bypasses via the <pack>:stdin-unverified rule.