Skip to content

Repository files navigation

Security Guardrails for Claude Code

A real-time security guardrails system that automatically scans code generated by Claude Code for vulnerabilities, secrets, and insecure patterns — and blocks dangerous actions before they execute.

Built with Claude Code hooks, a Node.js scanning engine, and a React dashboard.

Dashboard Overview


Table of Contents


What It Does

1. Blocks Dangerous Code Before It's Written

When Claude Code tries to write a file containing secrets, SQL injection, eval(), or other vulnerabilities — the PreToolUse hook blocks the write and tells Claude to fix it:

Hook Blocking

2. Blocks Dangerous Shell Commands

When Claude Code tries to run rm -rf /, git push --force main, cat .env, DROP DATABASE, or other destructive commands — they get denied before execution:

🚨 [rm-root] Dangerous command blocked: rm targeting root filesystem
   Command: rm -rf /

⛔ [git-force-main] Dangerous command blocked: Force push to main/master
   Command: git push --force origin main

⛔ [cat-env] Dangerous command blocked: Reading .env file — may expose secrets
   Command: cat .env

3. Scans Code for Vulnerabilities

Run manual scans on any codebase to find secrets, OWASP vulnerabilities, insecure dependencies, and dangerous code patterns:

CLI Scan Output

4. Real-Time Dashboard

Monitor everything in a live dashboard — security score, severity breakdown, category distribution, hook activity log, and detailed findings:

Full Dashboard


Screenshots

Dashboard — Score, Charts & Activity Log

Dashboard Score & Charts

Security score gauge (0-100), severity bar chart, category donut chart, and hook activity log showing blocked events with timestamps, tools, and reasons.

CLI — Scan Report

CLI Output

Terminal output showing scan results with color-coded severity, file locations, descriptions, and code snippets.

Hooks — Blocking Dangerous Actions

Hook Blocking

PreToolUse hook blocking dangerous Bash commands (rm -rf, force push, curl|bash, cat .env) and malicious code writes (AWS keys, hardcoded passwords).


Quick Start

Prerequisites

  • Node.js >= 18
  • npm >= 9
  • Claude Code CLI installed (install guide)
  • Docker (optional)

Install

# Clone the repo
git clone https://github.com/yourusername/claude-security-guardrails.git
cd claude-security-guardrails

# Install dependencies
npm install

Set Up Hooks

npm run setup-hooks

Output:

+ PreToolUse hook installed (BLOCKS writes with critical/high issues)
+ PostToolUse hook installed (reports findings + saves to dashboard)

── How it works ──────────────────────────────────
  PreToolUse  → Runs BEFORE Write/Edit/Bash
                🚫 BLOCKS dangerous commands (rm -rf, force push, etc.)
                🚫 BLOCKS code with secrets/vulnerabilities
  PostToolUse → Runs AFTER Write/Edit
                📊 Scans file, saves results to dashboard
──────────────────────────────────────────────────

Run a Test Scan

npm run scan -- ./test-fixtures/

Start the Dashboard

npm run dev

Open http://localhost:5173 in your browser.

That's it. Hooks are active, the scanner is ready, and the dashboard is live.


Running with Docker

No database required. Single container serves both the API and dashboard.

Docker Compose (Recommended)

# Build and start
docker compose up -d

# View logs
docker compose logs -f

# Stop
docker compose down

Docker Manual

# Build
docker build -t claude-security-guardrails .

# Run
docker run -d -p 3001:3001 --name security-guardrails claude-security-guardrails

Open http://localhost:3001 — both the API and the dashboard are served from the same port.

Persistent Data

Docker Compose uses a named volume scan-data to persist scan results and activity logs across container restarts.


Commands Reference

Command Description
npm install Install all dependencies
npm run setup-hooks Install Claude Code hooks (one-time)
npm run scan -- <path> Scan a file or directory
npm run scan -- <path> --json Scan with JSON output
npm run scan -- <path> --dry-run Scan without saving results
npm run scan:results Show latest scan results as JSON
npm run server Start API server only (port 3001)
npm run dashboard Start dashboard only (port 5173)
npm run dev Start both API + dashboard
docker compose up -d Run everything in Docker
docker compose down Stop Docker

Using Personally

You can use this on your own machine for all your Claude Code projects. Here's how:

Option A: Per-Project (Current Setup)

The default setup. Hooks only activate when Claude Code is working inside this project directory.

cd claude-security-guardrails
npm run setup-hooks    # hooks written to .claude/settings.json in this project

Pros: No impact on other projects, easy to customize per-project. Cons: Only protects this one project.

Option B: Global — Protect All Projects

Install hooks globally so they activate in every project you use Claude Code in.

Step 1: Copy hook scripts to a permanent location:

mkdir -p ~/.claude/hooks
cp hooks/pre-tool-use.js ~/.claude/hooks/
cp hooks/post-tool-use.js ~/.claude/hooks/

# Also copy the scanner (hooks depend on it)
cp -r scanner/ ~/.claude/hooks/scanner/

Step 2: Edit ~/.claude/settings.json (global config):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|Bash",
        "hooks": [{
          "type": "command",
          "command": "node ~/.claude/hooks/pre-tool-use.js"
        }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{
          "type": "command",
          "command": "node ~/.claude/hooks/post-tool-use.js"
        }]
      }
    ]
  }
}

Step 3: Update the require() paths inside the copied hook scripts to point to the new scanner location (~/.claude/hooks/scanner/...).

Now every Claude Code session on your machine is protected — regardless of which project you're in.

Option C: Dashboard Always Running

Keep the dashboard running as a background service to monitor all Claude Code activity:

# Add to your shell profile (.zshrc / .bashrc)
alias security-dashboard="cd ~/claude-security-guardrails && npm run dev"

Or use Docker:

docker run -d --restart unless-stopped -p 3001:3001 --name security-guardrails claude-security-guardrails

The dashboard is always at http://localhost:3001.


Using in Your Organisation

The Problem

When teams use Claude Code, AI-generated code can introduce:

  • Hardcoded secrets (API keys, passwords, connection strings)
  • OWASP vulnerabilities (SQL injection, XSS, command injection)
  • Dangerous commands (rm -rf, force push to main, DROP DATABASE)
  • Insecure dependencies and code patterns

You want guardrails that protect every developer automatically, without relying on individual discipline.

Option 1: Ship Hooks in Every Repo (Recommended for Teams)

Add the .claude/ directory and hooks to your organisation's repos. When any developer clones the repo and uses Claude Code, hooks activate automatically.

What to add to each repo:

your-org-repo/
├── .claude/
│   └── settings.json          ← hooks auto-activate
├── .claude-hooks/
│   ├── pre-tool-use.js        ← blocking hook
│   ├── post-tool-use.js       ← reporting hook
│   └── scanner/               ← scanning engine
│       ├── scanners/
│       │   ├── secrets.js
│       │   ├── owasp.js
│       │   ├── codePatterns.js
│       │   └── dangerousCommands.js
│       └── utils/
│           ├── severity.js
│           └── activityLog.js
└── src/
    └── ...

.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write|Edit|Bash",
      "hooks": [{
        "type": "command",
        "command": "node .claude-hooks/pre-tool-use.js"
      }]
    }],
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{
        "type": "command",
        "command": "node .claude-hooks/post-tool-use.js"
      }]
    }]
  }
}

Pros: Zero setup for developers, version-controlled, customizable per-repo. Cons: Need to add to each repo (automate with a template or CI step).

Option 2: Claude Code Enterprise Managed Settings

For Claude Code on an enterprise plan, admins can enforce hooks via managed settings that developers cannot override.

Via environment variable (set in MDM profiles, login scripts, or CI):

export CLAUDE_SETTINGS_OVERRIDES='{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write|Edit|Bash",
      "hooks": [{
        "type": "command",
        "command": "node /opt/company/claude-hooks/pre-tool-use.js"
      }]
    }]
  }
}'

Via managed policy file (distributed via MDM/Chef/Puppet/Ansible):

Place at a system-level path that Claude Code reads on startup. This ensures hooks are enforced even if a developer modifies their local settings.

Pros: Enforced org-wide, developers can't disable it, centrally managed. Cons: Requires enterprise plan, MDM/deployment infrastructure.

Option 3: Centralised Dashboard for Org-Wide Visibility

Run the dashboard as a shared service that all developer hooks report to:

Step 1: Deploy the dashboard on an internal server:

# On your internal server / Kubernetes / ECS
docker compose up -d

Step 2: Configure developer hooks to POST activity to the central server:

Update activityLog.js to send events to a central API in addition to (or instead of) local file storage. This gives you:

  • Org-wide view of what Claude Code is doing across all developers
  • Central log of all blocked commands and code writes
  • Aggregated security metrics for compliance reporting

Step 3: Set up alerts (Slack, PagerDuty, email) for critical blocked events.

Option 4: Git Hooks + CI/CD Integration

In addition to Claude Code hooks, add the scanner to your CI/CD pipeline:

# .github/workflows/security-scan.yml
name: Security Scan
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install
      - run: npm run scan -- . --json > scan-results.json
      - name: Check for critical issues
        run: |
          CRITICALS=$(node -e "const r=require('./scan-results.json'); console.log(r.severityCounts.critical)")
          if [ "$CRITICALS" -gt 0 ]; then
            echo "::error::Found $CRITICALS critical security issues"
            exit 1
          fi

This gives you a safety net even if someone bypasses local hooks.

Recommended Org Setup

Layer What How
Developer machine Block dangerous actions in real-time Hooks via per-repo .claude/settings.json or enterprise managed settings
Central dashboard Org-wide visibility + monitoring Docker on internal server
CI/CD Safety net for anything that slips through GitHub Actions / GitLab CI running the scanner
Alerts Immediate notification on critical events Slack/PagerDuty integration on the dashboard

How Hooks Work

Architecture

Claude Code tries to write code or run a command
         │
         ▼
┌─────────────────────────────────────┐
│  PreToolUse Hook                    │
│  ✓ Write/Edit → Scan for secrets,  │
│    vulnerabilities, insecure code   │
│  ✓ Bash → Check for dangerous      │
│    commands (rm -rf, force push)    │
└──────────────┬──────────────────────┘
        ┌──────┴──────┐
    BLOCKED       ALLOWED
   (denied)     (executed)
                    │
                    ▼
          ┌────────────────────┐
          │  PostToolUse Hook  │
          │  Full scan + save  │
          │  results to        │
          │  dashboard         │
          └────────────────────┘

Protocol

Hook scripts communicate with Claude Code via stdin/stdout JSON:

Claude Code → pipes JSON to hook's stdin:
  { "tool_name": "Bash", "tool_input": { "command": "rm -rf /" } }

Hook → writes JSON to stdout:

  Allow:  {}
  Block:  { "hookSpecificOutput": {
              "hookEventName": "PreToolUse",
              "permissionDecision": "deny",
              "permissionDecisionReason": "🚨 rm targeting root filesystem"
            }}

Scope

Settings location Scope
.claude/settings.json (in project) This project only
~/.claude/settings.json (home dir) All projects for this user
CLAUDE_SETTINGS_OVERRIDES env var Enforced, cannot be overridden

What Gets Detected

Secrets (10 patterns)

Pattern Severity
AWS Access Keys (AKIA...) Critical
AWS Secret Keys Critical
GitHub Tokens (ghp_, gho_, etc.) Critical
Private Keys (-----BEGIN RSA PRIVATE KEY-----) Critical
Database Connection Strings (mongodb://, postgres://) Critical
Slack Tokens (xoxb-...) Critical
API Keys High
JWT Tokens (eyJ...) High
Hardcoded Passwords High
Generic Secrets/Tokens Medium

OWASP Top 10 (13 patterns)

Pattern Severity
SQL Injection (string concat in queries) Critical
Command Injection (exec() with user input) Critical
XSS (innerHTML, dangerouslySetInnerHTML, document.write) High
SSRF (fetch/axios with user-controlled URLs) High
Path Traversal (file ops with user input) High/Medium
CORS Misconfiguration (origin: '*') Medium

Dangerous Commands (30+ patterns)

Category Examples Severity
Filesystem destruction rm -rf /, rm -rf ~/, rm -rf . Critical
Disk wipe dd of=/dev/sda, mkfs Critical
Fork bombs :(){ :|:& };: Critical
Git disasters git push --force main, git reset --hard, git clean -f High
Remote code execution curl | bash, wget | sh High
Secrets exposure cat .env, printenv, echo $SECRET_KEY High
Database destruction DROP DATABASE, TRUNCATE TABLE High
System commands shutdown, reboot, killall, chmod 777 High
Data exfiltration curl -d @.env, scp .env, rsync secrets High

Dependencies (16 known vulnerable packages)

Checks package.json for outdated packages with known CVEs (lodash, jsonwebtoken, shell-quote, axios, minimist, etc.) and flags wildcard/broad version ranges.

Code Patterns (11 patterns)

Pattern Severity
eval() usage Critical
new Function() constructor High
MD5 hashing for passwords High
Disabled TLS (rejectUnauthorized: false) High
Math.random() for security purposes Medium
Sensitive data in console.log() Medium
Hardcoded IPs and ports Low

Safety Levels

The PreToolUse hook has a configurable safety level in hooks/pre-tool-use.js:

const SAFETY_LEVEL = 'high'; // 'critical' | 'high' | 'strict'
Level What gets blocked
critical Only catastrophic: leaked secrets, eval(), rm -rf /, fork bombs
high (default) + risky: XSS, SQL injection, force push main, git reset --hard, weak crypto
strict + cautionary: all medium/low findings, any force push, sudo rm, docker prune

API Endpoints

Endpoint Method Description
/api/results GET All scan results (array)
/api/results/latest GET Most recent scan result
/api/summary GET Aggregated summary (score, counts)
/api/activity GET Recent hook events (blocked/allowed/findings)
/api/activity/stats GET Blocked/allowed/warning counts
/api/health GET Health check

Project Structure

claude-security-guardrails/
├── package.json                    # Root workspace config
├── Dockerfile                      # Multi-stage Docker build
├── docker-compose.yml              # Docker Compose config
├── README.md                       # This file
├── assets/                         # Screenshots
│   ├── dashboard-overview.png
│   ├── dashboard-full.png
│   ├── dashboard-score-charts.png
│   ├── cli-scan-output.png
│   └── hook-blocking.png
├── scanner/                        # Scanning engine
│   ├── index.js                    # Orchestrator
│   ├── cli.js                      # CLI interface
│   ├── server.js                   # Express API server
│   ├── scanners/
│   │   ├── secrets.js              # 10 secret patterns
│   │   ├── owasp.js                # 13 OWASP patterns
│   │   ├── dependencies.js         # 16 vulnerable packages
│   │   ├── codePatterns.js         # 11 code patterns
│   │   └── dangerousCommands.js    # 30+ dangerous commands
│   ├── utils/
│   │   ├── fileUtils.js
│   │   ├── severity.js
│   │   ├── store.js
│   │   └── activityLog.js
│   └── data/                       # Auto-created
│       ├── scan-results.json
│       └── activity-log.json
├── hooks/                          # Claude Code hooks
│   ├── pre-tool-use.js             # BLOCKING hook
│   ├── post-tool-use.js            # Reporting hook
│   └── setup-hooks.js              # Installer
├── dashboard/                      # React + Vite
│   └── src/
│       └── components/
│           ├── SecurityScore.jsx
│           ├── SeverityChart.jsx
│           ├── CategoryBreakdown.jsx
│           ├── ActivityLog.jsx
│           ├── RecentScans.jsx
│           ├── FindingsTable.jsx
│           └── Header.jsx
├── test-fixtures/                  # Sample vulnerable files
└── .claude/
    └── settings.json               # Hook configuration

Logging

All hook activity is logged in two places:

1. File logs (per developer):

~/.claude/hooks-logs/2026-02-19.jsonl

2. Dashboard logs (visible in UI):

scanner/data/activity-log.json

Example log entry:

{
  "id": "evt_1771501445272_wvx6",
  "timestamp": "2026-02-19T11:44:05.272Z",
  "action": "blocked",
  "hook": "PreToolUse",
  "tool": "Bash",
  "target": "rm -rf /",
  "reason": "rm targeting root filesystem",
  "severity": "critical",
  "patternId": "rm-root"
}

License

MIT

About

A security layer for Claude Code that uses PreToolUse/PostToolUse hooks to automatically scan and block dangerous operations — rm -rf, force pushes, leaked API keys, SQL injection, eval(), and 30+ risky patterns — before they execute. Includes a real-time React dashboard for monitoring blocked events and security findings.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages