DEV Community

Cover image for Open Source Project of the Day (#124): Destructive Command Guard — Intercept rm -rf Before Your AI Agent Runs It
WonderLab
WonderLab

Posted on

Open Source Project of the Day (#124): Destructive Command Guard — Intercept rm -rf Before Your AI Agent Runs It

Introduction

"AI agents occasionally run catastrophic commands — rm -rf ./src, git reset --hard, DROP TABLE users — destroying hours of uncommitted work instantly."

This is article #124 in the Open Source Project of the Day series. Today's project is Destructive Command Guard (dcg) — a Rust hook that intercepts dangerous commands before AI coding agents execute them.

You may have encountered this scenario: you ask Claude Code to clean up temporary files and it uses rm -rf to delete the entire src directory. Or you ask it to reset a Git state and git reset --hard wipes two hours of uncommitted work.

This isn't the AI model becoming dumb. AI agents understand what commands do, but they may underestimate the cost given your specific current state. The gap between "what the command does" and "what it means for this particular moment" is where accidents happen.

dcg's solution: put a gate before command execution, intercept known dangerous patterns, and return decision authority to the human.

What You'll Learn

  • dcg's four-stage processing pipeline: how it makes an interception decision in under a millisecond
  • Context awareness — the critical design: why grep "rm -rf" should not be blocked
  • Coverage of 50+ security packs
  • Heredoc scanning: handling python -c "os.remove()" style implicit commands
  • Three bypass mechanisms and their design intent
  • Claude Code PreToolUse hook integration

Prerequisites

  • Regular use of Claude Code, Cursor, or similar AI coding tools
  • Familiarity with basic shell commands and Git operations
  • Direct or secondhand experience with AI agents executing dangerous operations helps contextualize the value

Project Background

What Is dcg?

Destructive Command Guard (dcg) is a protection tool that hooks into the command execution layer of AI coding agents. Written in Rust, it integrates as a PreToolUse hook in Claude Code's execution flow.

Before a command is executed, it passes through dcg's filter. If the command matches a known dangerous pattern, dcg outputs an interception message and the command doesn't run. If determined safe, the command executes normally with under 1ms latency.

Author

  • Jeffrey Emanuel: Original Python concept, expanded Rust implementation (pack system, Heredoc scanning, context classification)
  • Darin Gordon: Initial Rust port and performance optimizations
  • License: MIT

Project Stats

  • ⭐ GitHub Stars: 4,400+
  • 🍴 Forks: 165+
  • 📄 License: MIT
  • 🦀 Language: Rust (Edition 2024, nightly)

Four-Stage Processing Pipeline

Every command from agent intent to actual execution passes through four stages:

AI agent intends to execute a command
        ↓
Stage 1: JSON Parsing
        Receive PreToolUse hook JSON payload
        Extract command string
        Invalid payload → fail-open (pass through)
        ↓
Stage 2: Command Normalization
        /usr/bin/git → git
        /opt/homebrew/bin/python3 → python3
        Eliminates false positives from absolute paths
        ↓
Stage 3: Quick Filter
        SIMD-accelerated substring scan
        Skips 99%+ of safe commands instantly
        Suspicious keywords → full analysis
        ↓
Stage 4: Pattern Matching
        Check allowlist first (safe patterns)
        Then check denylist (dangerous patterns)
        Deny → output block message + alternative suggestion
        Allow → command executes normally

Total latency: < 1ms (200ms absolute timeout, then fail-open)
Enter fullscreen mode Exit fullscreen mode

Fail-open design principle: When dcg itself encounters errors (parse failure, timeout, unexpected panic), it chooses to pass the command through rather than block it. This ensures dcg's own bugs can't freeze your workflow — security protection is an additive layer, not a new failure point.


Default-On Protection

No configuration needed after installation. The following protection is immediate:

core.filesystem (permanent, cannot be disabled)

Blocks dangerous deletion operations outside temp directories:

# Will be blocked:
rm -rf ./src
rm -rf ~/Documents
find . -name "*.js" -delete

# Won't be blocked (legitimate operations):
rm -rf /tmp/build_cache
rm /tmp/test_output.log
Enter fullscreen mode Exit fullscreen mode

core.git (default on)

Blocks Git operations that destroy commit history or uncommitted work:

# Will be blocked:
git reset --hard HEAD~5       # destroys uncommitted changes
git push --force              # overwrites remote history
git clean -fd                 # deletes untracked files
git rebase --root             # rewrites entire history

# Block message example:
# ════════════════════════════════════════════════
# BLOCKED  dcg
# ────────────────────────────────────────────────
# Reason:  git reset --hard destroys uncommitted changes
# Command: git reset --hard HEAD~5
# Tip:     Consider using 'git stash' first.
# ════════════════════════════════════════════════
Enter fullscreen mode Exit fullscreen mode

system.disk (default on)

Blocks disk-level dangerous operations:

# Will be blocked:
mkfs.ext4 /dev/sda
dd if=/dev/zero of=/dev/sdb
fdisk /dev/sda
Enter fullscreen mode Exit fullscreen mode

Context Awareness: The Critical Design

dcg must distinguish between "a command string appearing in data context" and "a command string in execution context":

# These should NOT be blocked:
grep "rm -rf" README.md         # searching for a string, not executing
cat ~/.bashrc | grep "reset"    # viewing config, not executing
echo "never run: rm -rf /"      # outputting a string

# These SHOULD be blocked:
rm -rf ./important_dir
$(rm -rf /)                     # dangerous command in command substitution
`git reset --hard`              # backtick execution
Enter fullscreen mode Exit fullscreen mode

The context classification module analyzes the semantic role of the command — is it being passed as an argument to grep/echo/cat, or is it a standalone executable command? That determination drives the decision.


Heredoc and Inline Code Scanning

This is a capability most similar tools lack — scanning inline code passed to interpreters:

# These attack patterns are scanned:
python -c "import os; os.remove('/etc/passwd')"
python -c "import shutil; shutil.rmtree('./src')"
bash -c "rm -rf /var/log/*"
node -e "require('fs').rmdirSync('./dist', {recursive: true})"

# Heredoc form:
python3 << 'EOF'
import os
os.remove('/important/file')
EOF
Enter fullscreen mode Exit fullscreen mode

dcg uses tree-sitter and ast-grep to parse inline code, finding dangerous operations inside it rather than doing naive string matching.


50+ Opt-In Security Packs

Beyond default protection, packs can be enabled as needed:

Databases:

[packs]
"db.postgres" = true    # DROP TABLE, TRUNCATE, DELETE without WHERE
"db.mysql" = true
"db.mongodb" = true
"db.redis" = true       # FLUSHALL, FLUSHDB
"db.sqlite" = true
Enter fullscreen mode Exit fullscreen mode

Kubernetes:

"k8s.kubectl" = true    # delete namespace, force delete pods
"k8s.helm" = true       # helm delete, helm rollback
Enter fullscreen mode Exit fullscreen mode

Cloud:

"cloud.aws" = true      # s3 rm --recursive, ec2 terminate-instances
"cloud.gcp" = true
"cloud.azure" = true
Enter fullscreen mode Exit fullscreen mode

Docker:

"containers.docker" = true  # docker rm -f, docker system prune -a
Enter fullscreen mode Exit fullscreen mode

Terraform:

"iac.terraform" = true  # terraform destroy, terraform state rm
Enter fullscreen mode Exit fullscreen mode

Example block with db.redis enabled:

# Will be blocked:
redis-cli FLUSHALL             # wipes entire Redis instance
redis-cli FLUSHDB              # wipes current database
Enter fullscreen mode Exit fullscreen mode

Three Bypass Mechanisms

dcg is bypassable by design. The goal is "add friction," not "make it impossible":

Method 1: Single-command bypass (temporary)

DCG_BYPASS=1 git reset --hard HEAD~5
Enter fullscreen mode Exit fullscreen mode

The environment variable only affects this one execution. The same command will still be blocked next time.

Method 2: One-time exception

dcg allow-once <code>   # code from the authorization code in the block message
Enter fullscreen mode Exit fullscreen mode

Appropriate when you need to execute one specific operation without affecting future blocking rules.

Method 3: Permanent allowlist

dcg allowlist add "git reset --hard HEAD"   # allow this specific command
dcg allowlist add "rm -rf ./dist"           # allow cleaning build directory
Enter fullscreen mode Exit fullscreen mode

Written to config file, permanent.


Claude Code Integration

# One-line install (easy-mode auto-configures Claude Code hook)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --easy-mode
Enter fullscreen mode Exit fullscreen mode

This registers a PreToolUse hook in Claude Code's configuration. From that point, every command Claude Code prepares to execute passes through dcg first.

Manual configuration (~/.claude/settings.json):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "dcg"
          }
        ]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

CI Scan Mode

Beyond real-time interception, dcg has a scan command for auditing dangerous commands already committed to a repository:

# Scan current repository
dcg scan ./

# Scan specific file types
dcg scan ./ --include "*.sh,*.yml,Dockerfile,Makefile"
Enter fullscreen mode Exit fullscreen mode

The scanner understands execution context:

  • RUN rm -rf /var/cache/* in Dockerfile (reasonable, inside build layer)
  • - run: kubectl delete namespace prod in GitHub Actions workflow (worth flagging)
  • clean: rm -rf ./dist in Makefile (reasonable, clear intent)
  • rm -rf $TMPDIR in shell script (check whether TMPDIR might have unexpected value)

Links and Resources


Conclusion

Destructive Command Guard addresses a new risk category that comes with AI coding tool adoption: AI agents have a much broader operational scope than previous automation tools. They actually run shell commands, manipulate file systems, and execute Git operations. A misjudgment now causes much more damage than running a wrong command the old way.

dcg's design philosophy is "add friction rather than block completely." It doesn't prevent you from doing anything — it just inserts a confirmation step before dangerous operations. Fail-open design ensures it never becomes a failure point itself. Context awareness and Heredoc scanning keep the false positive rate low enough not to interrupt normal work.

The 50+ security pack coverage extends the protection well beyond the obvious "prevent rm -rf" use case, bringing production-level dangerous operations in databases, Kubernetes, and cloud services into the protection scope.

For engineers already using Claude Code or similar tools in daily development, the cost to install dcg is minimal. The safety margin it provides is worth having.


Explore PrimeSkills — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.

Welcome to my Homepage for more useful insights and interesting products.

Top comments (0)