P4 โ€” Mini-CRS (Cyber Reasoning System)


What It Does

Point it at a C source directory. Come back to a report with CWEs identified, patches generated, and patches validated โ€” fully autonomous. No manual input required after launch.

Pipeline

Target C source
      โ†“
  Build         afl-clang-fast + AddressSanitizer instrumentation
      โ†“
  Fuzz          AFL++ coverage-guided fuzzing โ†’ crash corpus
      โ†“
  Triage        ASan output + GDB backtrace + stack hash dedup
      โ†“
  Analyze       LLM โ†’ CWE ID, root cause, attack scenario, severity
      โ†“
  Patch         LLM โ†’ unified diff โ†’ patch -p1 โ†’ recompile โ†’ validate
      โ†“
  Report        Executive HTML + JSON with diffs and validation results

Demo Results

Running against the built-in vulnerable C parser (120s fuzz):

FindingCWECrash TypePatch
strcpy heap overflowCWE-120Heap Buffer Overflow @ parse_nameโœ“ Fixed
printf format stringCWE-134Format String @ log_recordโœ“ Fixed

100% fix rate. Both patches compiled clean and passed crash-file validation.

LLM Providers

ProviderBackend
ollamaLocal Ollama โ€” on-prem, no data egress
claudeAnthropic Messages API
openaiOpenAI Chat Completions
openai-compatvLLM, LM Studio, any OpenAI-compatible endpoint

Engineering Details

Binary-safe subprocess output โ€” AFL crash files contain raw binary. text=True in Python subprocess raises UnicodeDecodeError. Fixed with text=False + decode('utf-8', errors='replace') throughout the triage and validation pipeline.

Hunk header auto-correction โ€” LLMs frequently emit incorrect @@ -X,Y +X,Z @@ counts when generating unified diffs, especially when inserting multiple lines into a single hunk. The patcher recomputes all hunk counts from the actual diff content before applying.

Source restore after validation โ€” The patcher applies each diff, compiles, runs the crash file against the patched binary, then restores the original source regardless of result. Patches are preserved in the Patch.diff field. Without this, re-runs build from patched code and crash files no longer trigger โ€” making triage useless.

Stack hash deduplication โ€” Extracts top-5 user-space frame names (skipping ASan/libc internals) and SHA-1 hashes them. Two AFL crash files that hit the same code path are reported once.

Usage

# Full pipeline โ€” 120s fuzz on demo target, Claude LLM
python crs.py --target targets/vulnerable_parser --fuzz-time 120 \
  --llm-provider claude --llm-model claude-haiku-4-5-20251001

# Local Ollama
python crs.py --target targets/vulnerable_parser --fuzz-time 60

# Skip fuzzing, use pre-made crash corpus
python crs.py --target targets/vulnerable_parser --no-fuzz \
  --crashes targets/vulnerable_parser/crashes/

# Your own C target
python crs.py --target /path/to/c/source/ --seeds /path/to/seeds/ \
  --fuzz-time 300 --llm-provider claude
โ† back