Skip to content

backspace-shmackspace/deep-code-security

Repository files navigation

deep-code-security

Multi-language SAST tool with agentic verification and AI-powered fuzzing. Two analysis modes:

  1. Static Analysis (SAST) - Uses Semgrep with tree-sitter fallback for deterministic AST parsing, sandbox-verified exploit PoCs, and structured remediation guidance
  2. Dynamic Analysis (Fuzzing) - AI-powered fuzzer with coverage-guided feedback, crash deduplication, and corpus management

Exposes all functionality via an MCP server for Claude Code integration.

Quick Start

# Install (basic)
pip install -e ".[dev]"

# Install with fuzzing support
pip install -e ".[dev,fuzz]"

# Static analysis via CLI
dcs hunt /path/to/project
dcs hunt /path/to/project --ignore-suppressions
dcs verify --finding-ids <id1> <id2>

# Dynamic analysis (fuzzing) via CLI
dcs fuzz /path/to/target.py
dcs replay /path/to/corpus
dcs corpus /path/to/corpus
dcs fuzz-plugins
dcs report /path/to/output

# Integrated SAST-to-Fuzz pipeline
dcs hunt-fuzz /path/to/project

# Enable C fuzzing (in addition to Python)
export DCS_FUZZ_ALLOWED_PLUGINS=python,c

# Build the C fuzzer sandbox (Podman required)
make build-fuzz-c-sandbox

# Fuzz a C target with SAST-to-Fuzz bridge
dcs hunt-fuzz /path/to/c_project --consent

# Run via MCP server
python -m deep_code_security.mcp

Architecture

Static Analysis (SAST)

Target Codebase
    |
    v
HUNTER     scanner backend (Semgrep/tree-sitter) → source/sink match → taint track
    |      Output: RawFinding[] (JSON, paginated)
    v
AUDITOR    PoC generation → sandbox execution → confidence scoring
    |      Output: VerifiedFinding[] (JSON)  [Exploit = 10% bonus only]
    v
ARCHITECT  context gather → guidance generation → dependency analysis
           Output: RemediationGuidance[] (JSON)

Dynamic Analysis (Fuzzing)

Target Function
    |
    v
FUZZER     LLM-guided input generation → sandboxed execution →
           crash detection → corpus management → coverage tracking
           Output: CrashReport[] (JSON, with reproducer inputs)

Supported Languages (v1)

  • Python (Flask, Django patterns; SAST + fuzzing)
  • Go (net/http, database/sql patterns; SAST only)
  • C (command injection, buffer overflow, format string, memory corruption patterns; SAST + fuzzing). C fuzzing requires DCS_FUZZ_ALLOWED_PLUGINS=python,c and AI-powered harness generation with AddressSanitizer and gcov instrumentation.

Suppression Files

You can suppress specific findings by creating a .dcs-suppress.yaml file in your project root. This is useful for marking false positives, accepted risks, or findings that will be addressed later.

Basic usage:

# .dcs-suppress.yaml
version: 1
suppressions:
  - rule: CWE-22
    file: "src/config/*.py"
    reason: "Config paths are admin-controlled"

  - rule: CWE-89
    file: "src/legacy/db.py"
    line: 145
    reason: "Legacy code scheduled for refactor in Q2"

CLI flags:

  • By default, suppressions are applied during dcs hunt, dcs full-scan, and dcs hunt-fuzz commands
  • Use --ignore-suppressions to bypass the suppression file and show all findings

Notes:

  • Suppression files only affect SAST findings, not fuzzer crashes
  • The file must be named .dcs-suppress.yaml and located in the project root
  • All formatters (text, JSON, SARIF, HTML) show suppression statistics in their output

Installation

# Clone
git clone https://github.com/your-org/deep-code-security.git
cd deep-code-security

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

# Install with fuzzing support (requires anthropic SDK)
pip install -e ".[dev,fuzz]"

# Build sandbox images (requires Docker or Podman)
make build-sandboxes        # Build auditor/architect sandbox images
make build-fuzz-sandbox     # Build Python fuzzer sandbox image (Podman only)
make build-fuzz-c-sandbox   # Build C fuzzer sandbox image (Podman only)

MCP Configuration

Add to ~/.claude/settings.json:

{
  "mcpServers": {
    "deep-code-security": {
      "command": "python",
      "args": ["-m", "deep_code_security.mcp"],
      "cwd": "/path/to/deep-code-security",
      "env": {
        "DCS_REGISTRY_PATH": "/path/to/deep-code-security/registries",
        "DCS_ALLOWED_PATHS": "/path/to/projects",
        "DCS_CONTAINER_RUNTIME": "auto",
        "ANTHROPIC_API_KEY": "your-api-key-here"
      }
    }
  }
}

Optional Environment Variables

For advanced tuning, additional variables are available:

Static Analysis:

Variable Default Description
DCS_SCANNER_BACKEND auto Scanner backend: semgrep, treesitter, or auto (prefer semgrep if available)
DCS_SEMGREP_TIMEOUT 120 Maximum seconds for Semgrep subprocess
DCS_SEMGREP_RULES_PATH <registry>/semgrep Path to DCS Semgrep rule files
DCS_MAX_RESULTS 100 Max findings returned per hunt operation
DCS_MAX_VERIFICATIONS 50 Max findings to verify in auditor phase
DCS_SANDBOX_TIMEOUT 30 Per-exploit timeout in seconds
DCS_MAX_FILES 10000 Max files per scan
DCS_MAX_CONCURRENT_SANDBOXES 2 Concurrency limit for sandbox execution
DCS_QUERY_TIMEOUT 5.0 Tree-sitter query timeout in seconds
DCS_QUERY_MAX_RESULTS 1000 Max results per tree-sitter query
DCS_BRIDGE_MAX_TARGETS 10 Max fuzz targets produced by SAST-to-Fuzz bridge

Dynamic Analysis (Fuzzing):

Variable Default Description
ANTHROPIC_API_KEY (none) API key for Claude (required for fuzzing)
GOOGLE_CLOUD_PROJECT (none) GCP project ID for Vertex AI (optional)
CLOUD_ML_PROJECT_NUMBER (none) GCP project number for Vertex AI (optional)
ANTHROPIC_VERTEX_PROJECT_ID (none) Vertex AI project override (optional)
DCS_FUZZ_MODEL claude-sonnet-4-6 Claude model for input generation
DCS_FUZZ_MAX_ITERATIONS 10 Max fuzzing iterations
DCS_FUZZ_INPUTS_PER_ITER 10 Inputs generated per iteration
DCS_FUZZ_TIMEOUT_MS 5000 Per-input execution timeout
DCS_FUZZ_MAX_COST_USD 5.0 API cost budget
DCS_FUZZ_OUTPUT_DIR ./fuzzy-output Corpus and report output directory
DCS_FUZZ_CONSENT false Pre-configured consent for CI
DCS_FUZZ_GCP_REGION us-east5 GCP region for Vertex AI
DCS_FUZZ_ALLOWED_PLUGINS python Comma-separated allowlist of fuzzer plugins (default: python; set to python,c to enable both)
DCS_FUZZ_MCP_TIMEOUT 120 Hard wall-clock timeout for MCP fuzz invocations
DCS_FUZZ_CONTAINER_IMAGE dcs-fuzz-python:latest Podman image used by ContainerBackend for MCP fuzz runs
DCS_FUZZ_C_CONTAINER_IMAGE dcs-fuzz-c:latest Podman image used by CContainerBackend
DCS_FUZZ_C_COMPILE_FLAGS "" Comma-separated gcc flags (e.g., -O2,-march=native)
DCS_FUZZ_C_INCLUDE_PATHS "" Comma-separated include paths for C harness compilation

MCP Tools

Tool Description
deep_scan_hunt Run Hunter phase (AST parse + taint track)
deep_scan_verify Run Auditor phase (sandbox exploit verification)
deep_scan_remediate Run Architect phase (remediation guidance)
deep_scan_full Run all three phases sequentially
deep_scan_status Check sandbox health and registry info
deep_scan_fuzz Run AI-powered fuzzing (requires Podman container backend)
deep_scan_hunt_fuzz Run SAST analysis followed by AI-powered fuzzing of identified vulnerable functions (requires Podman + consent)
deep_scan_fuzz_status Check fuzzer availability and configuration

Confidence Scoring

The confidence score (0-100) uses a weighted composite:

Factor Weight Notes
Taint path completeness 45% Full path = 100, partial = 50, heuristic = 20
Sanitizer absence 25% No sanitizer = 100, full sanitizer = 0
CWE severity baseline 20% Critical = 100, High = 75, Medium = 50, Low = 25
Exploit verification 10% Bonus only — failed PoC does not penalize

Thresholds: >=75 confirmed, >=45 likely, >=20 unconfirmed, <20 false positive

Sandbox Security Policy

Sandbox containers enforce:

  • --network=none — no network access
  • --read-only — read-only root filesystem
  • --tmpfs /tmp:rw,noexec,nosuid,size=64m — writable temp with noexec
  • --cap-drop=ALL — no Linux capabilities
  • --security-opt=no-new-privileges — no privilege escalation
  • --security-opt seccomp=seccomp-default.json — custom seccomp profile
  • --pids-limit=64 — no fork bombs
  • --memory=512m — memory ceiling
  • --user=65534:65534 — run as nobody

Development

make lint           # Lint with ruff
make test           # All tests (90%+ coverage required)
make test-hunter    # Hunter tests only
make test-auditor   # Auditor tests only
make test-architect # Architect tests only
make test-mcp       # MCP server tests only
make test-fuzzer    # Fuzzer tests only
make test-c-fuzzer  # C fuzzer plugin tests only
make sast           # Security scan with bandit
make security       # sast + pip-audit

Registry Format

See registries/README.md for the YAML registry format documentation.

Known Limitations (v1)

  1. Intraprocedural taint only — source and sink must be in the same function body. Expected detection rate: 10-25% of real-world injection vulnerabilities. Most web app vulnerabilities span multiple function call boundaries and will NOT be detected by v1.

  2. Query brittleness (tree-sitter backend only) — tree-sitter queries match specific AST shapes. When using Semgrep backend, aliased imports, fully-qualified names, and class attributes are handled correctly. The following patterns are NOT matched when using tree-sitter:

    • Aliased imports: req = request; req.form
    • Fully-qualified names: flask.request.form
    • Class attributes: self.request.form
    • Chained calls: request.form.get("key") (partial match only)
  3. PoC verification is bonus-only — most template-based PoCs fail due to missing execution context (framework setup, dependency injection, state initialization). A failed PoC does NOT mean the vulnerability is false. The exploit bonus is capped at 10 points.

  4. No cross-language taint — Python calling C via FFI is not analyzed. Each language is analyzed independently.

  5. No interprocedural analysis — call graphs across functions/files are not traced in v1. Deferred to v1.1.

  6. Fuzzer requires optional dependencies — dynamic analysis requires pip install -e ".[fuzz]" to install the anthropic SDK and related packages. The fuzzer will not be available without these dependencies.

  7. deep_scan_fuzz MCP tool requires Podman — The MCP fuzzing tool uses ContainerBackend for full isolation and is only available when Podman is installed and the dcs-fuzz-python:latest image is built via make build-fuzz-sandbox. CLI fuzzing supports both SubprocessBackend (rlimits-only) and ContainerBackend.

  8. C language: no preprocessor resolution#ifdef guards and macro expansions are invisible to the scanner. Code hidden behind conditional compilation will not be analyzed.

  9. C language: no struct member taint tracking — taint does not propagate through struct field assignments. Only scalar variables and direct pointer dereferences are tracked.

  10. C language: pointer aliasing tracked within same function only — intraprocedural constraint applies (same as limitation #1). Pointer aliases passed to other functions are not tracked.

  11. C language: output-parameter sources deferred — C source functions that deliver tainted data via output parameters (recv, fread, read, scanf, getline, getdelim) are not effective taint sources in v1. Only functions whose return value is the tainted data (argv, getenv, gets, fgets) work correctly with the LHS-seeding taint engine.

  12. C language: CWE-416 (use-after-free) detection deferred — requires temporal ordering analysis (tracking that free(ptr) precedes a subsequent use of ptr), which is fundamentally different from the source-to-sink taint model.

  13. C language: mktemp()/tmpnam() detection gap — registered as CWE-676 sinks, but the taint-flow pipeline requires a source-to-sink path. Most real-world uses call these with hardcoded template strings, so they will NOT be flagged.

  14. C fuzzer harness validation is allowlist-based, not sandbox-escape-proof — The C fuzzer compiles and executes LLM-generated C code inside a Podman container with seccomp enforcement. Dual-layer AST validation prohibits dangerous syscalls and non-standard includes, but this is a defense-in-depth measure, not a complete security boundary. The primary isolation mechanism is the Podman container with --network=none, --read-only, --cap-drop=ALL, and a custom seccomp profile (sandbox/seccomp-fuzz-c.json). Prompt injection attacks that evade the AST allowlist could still execute arbitrary code inside the container (but not escape to the host).

Security Model

The MCP server runs as a native stdio process on the host. It does NOT run inside a Docker container, avoiding the Docker socket mount attack vector. Docker or Podman is used for sandbox containers that execute exploit PoCs (auditor/architect phases). The fuzzer's ContainerBackend uses Podman exclusively for rootless container execution.

All file access goes through DCS_ALLOWED_PATHS allowlist validation with symlink resolution. All RawFinding fields are validated before exploit template interpolation. Finding provenance is verified via server-side session store (external callers cannot inject arbitrary findings).

Fuzzer Execution Model

The Python and C fuzzers use fundamentally different execution models inside the sandbox container:

  • Python fuzzer (_worker.py): uses eval() with restricted globals (no imports, limited builtins) and dual-layer AST validation. No arbitrary machine code is generated.
  • C fuzzer (_c_worker.py): does NOT use eval(). Instead, AI-generated C source is compiled with gcc and the resulting binary is executed. This means arbitrary machine code runs inside the container, making the Podman seccomp profile (sandbox/seccomp-fuzz-c.json) the primary security boundary.

Both backends run under --network=none, --read-only, --cap-drop=ALL, --pids-limit=64, and --memory=512m.

v1.1 Roadmap

  • Interprocedural taint tracking (call graph construction)
  • Java and Rust language support
  • Additional registry patterns (aliased imports, fully-qualified names)
  • gVisor/Firecracker sandbox option for higher-risk deployments

About

Multi-language SAST tool with tree-sitter taint tracking, sandbox exploit verification, and MCP server interface

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages