Exploitability Validation & Exploit Feasibility Integration
This document explains how RAPTOR's two validation systems work together to ensure vulnerability findings are both real and exploitable.
The Problem
Security scanners and LLM-based analysis can produce findings that:
- Don't exist - Hallucinated files, functions, or code
- Aren't reachable - Dead code, test files, unrealistic preconditions
- Can't be exploited - System mitigations block all viable techniques
Investing in exploit development for any of these wastes significant time.
Two Validation Layers
RAPTOR addresses this with two complementary validation systems:
Layer 1: Exploitability Validation (Source-Level)
Question answered: "Is this finding REAL and REACHABLE?"
| Aspect | Details |
|---|---|
| Input | Source code + scanner findings |
| Validates | File exists, code accurate, flow real, not test code |
| Output | Validated findings with working PoCs |
| Location | .claude/skills/exploitability-validation/ |
Stages:
- Inventory - Build checklist of all code to analyze
- One-Shot - Quick exploitability verification + PoC
- Process - Systematic analysis with attack trees
- Sanity - Verify against actual code (catch hallucinations)
- Ruling - Filter test code, preconditions, hedging language
- Feasibility - Binary constraint analysis (memory corruption only, auto-bridges to exploit_feasibility)
Layer 2: Exploit Feasibility (Binary-Level)
Question answered: "CAN this be exploited given system mitigations?"
| Aspect | Details |
|---|---|
| Input | Compiled binary |
| Validates | PIE, NX, Canary, RELRO, glibc version, ROP gadgets, bad bytes |
| Output | Verdict (Likely/Difficult/Unlikely) + chain breaks |
| Location | packages/exploit_feasibility/ |
Checks:
- Binary protections (PIE, NX, Stack Canary, RELRO)
- Glibc mitigations (removed hooks, %n blocking)
- Input handler constraints (null bytes, bad characters)
- ROP gadget availability and quality
- Empirical verification (actually tests, not just checks)
How They Work Together
┌─────────────────────────────────────────────────────────────────────────────┐
│ SCANNER (Semgrep/CodeQL) │
│ "Found potential command injection in utils/shell.py:42" │
└─────────────────────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXPLOITABILITY VALIDATION - Stages 0-D (Source-Level) │
│ │
│ Stage 0: Inventory - enumerate all functions │
│ Stage A: One-shot - quick PoC attempt │
│ Stage B: Process - attack trees, hypotheses, multiple paths │
│ Stage C: Sanity - file exists? code verbatim? flow real? │
│ Stage D: Ruling - not test code? no unrealistic preconditions? │
│ │
│ RESULT: "Validated. Real vulnerability, reachable, PoC works." │
└─────────────────────────────────┬───────────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
Memory Corruption Web/Injection
(buffer overflow, (command injection,
format string, UAF) SQL injection, XSS)
│ │
▼ │
┌─────────────────────────────────────────┐ │
│ STAGE E: EXPLOIT FEASIBILITY │ │
│ (Automatic bridge to exploit_feasibility) │
│ │ │
│ Analyze binary constraints: │ │
│ - Full RELRO? → GOT blocked │ │
│ - glibc 2.38? → %n blocked │ │
│ - strcpy? → null bytes block ROP │ │
│ │ │
│ RESULT: verdict + chain_breaks + │ │
│ what_would_help + context_file │ │
└─────────────────────┬───────────────────┘ │
│ │
└───────────┬───────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ FINAL OUTPUT │
│ │
│ EXPLOITABLE: Clear path to code execution │
│ CONFIRMED_CONSTRAINED: Primitives exist but hard to chain │
│ CONFIRMED_BLOCKED: No viable path with current mitigations │
│ CONFIRMED: Web vuln (Stage E not applicable) │
└─────────────────────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXPLOIT DEVELOPMENT (/exploit) │
│ │
│ Now you know: │
│ - The vulnerability is REAL (not hallucinated) │
│ - The code is REACHABLE (not dead/test code) │
│ - Exploitation is POSSIBLE (or what constraints exist) │
│ - Context file persists across conversation compaction │
│ │
│ Proceed with confidence, using only viable techniques. │
└─────────────────────────────────────────────────────────────────────────────┘
When Each Layer Applies
| Vulnerability Type | Exploitability Validation | Exploit Feasibility |
|---|---|---|
| Command Injection | Yes | No (not memory corruption) |
| SQL Injection | Yes | No |
| XSS | Yes | No |
| Path Traversal | Yes | No |
| Buffer Overflow | Yes | Yes |
| Format String | Yes | Yes |
| Use-After-Free | Yes | Yes |
| Heap Overflow | Yes | Yes |
API Integration
Automatic (via Stage E)
Stage E automatically handles the integration for memory corruption vulnerabilities:
# Stage E does this automatically - see stage-e-feasibility.md
from packages.exploit_feasibility import (
analyze_binary,
format_analysis_summary,
save_exploit_context
)
MEMORY_CORRUPTION_TYPES = [
'buffer_overflow', 'heap_overflow', 'stack_overflow',
'format_string', 'use_after_free', 'double_free',
'integer_overflow', 'out_of_bounds_read', 'out_of_bounds_write'
]
for finding in confirmed_findings:
if finding.vuln_type in MEMORY_CORRUPTION_TYPES:
result = analyze_binary(binary_path, vuln_type=finding.vuln_type)
context_file = save_exploit_context(binary_path) # Always save
finding.feasibility = {
'status': 'analyzed',
'verdict': result.verdict,
'chain_breaks': result.chain_breaks,
'what_would_help': result.what_would_help,
'context_file': context_file # Survives conversation compaction
}
# Set final status based on verdict
finding.final_status = {
'Likely': 'EXPLOITABLE',
'Difficult': 'CONFIRMED_CONSTRAINED',
'Unlikely': 'CONFIRMED_BLOCKED'
}.get(result.verdict, 'CONFIRMED_UNVERIFIED')
Manual / Standalone
from packages.exploit_feasibility import analyze_binary, format_analysis_summary
# Full analysis
result = analyze_binary('/path/to/binary')
print(format_analysis_summary(result, verbose=True))
# Quick viability check
from packages.exploit_feasibility import check_exploit_viability
viable, reason = check_exploit_viability('/path/to/binary', 'format_string')
# Context persistence (for later use after compaction)
from packages.exploit_feasibility import save_exploit_context, load_exploit_context
context_file = save_exploit_context('/path/to/binary')
ctx = load_exploit_context(context_file)
MUST-GATEs (Validation Rigor)
The Exploitability Validation system enforces strict gates to prevent common LLM failure modes:
| Gate | Rule | Prevents |
|---|---|---|
| GATE-1 | Assume exploitable until proven otherwise | Premature dismissal |
| GATE-2 | Strict sequence, additional ideas separate | Methodology drift |
| GATE-3 | Track checklist compliance | Incomplete coverage |
| GATE-4 | Verify all "if/maybe/uncertain" claims | Unverified hedging |
| GATE-5 | Check ALL code, no sampling | Missed vulnerabilities |
| GATE-6 | Show proof for every finding | Hallucinations |
Output Files
Exploitability Validation
.out/exploitability-validation-<timestamp>/
├── checklist.json # Ground truth: all functions to check
├── findings.json # Validated findings with PoCs
├── attack-tree.json # Knowledge graph of attack surface
├── hypotheses.json # Tested exploitation hypotheses
├── disproven.json # Failed approaches (learning)
├── attack-paths.json # Paths tried + PROXIMITY tracking
├── attack-surface.json # Sources, sinks, trust boundaries
└── validation-report.md # Human-readable summary
Exploit Feasibility
.out/exploit-context-<binary>-<timestamp>.json
├── binary_info # Path, arch, protections
├── libc # Version, offsets, mitigations
├── gadgets # ROP gadget analysis
├── constraints # Input handler bad bytes
├── verdict # Likely/Difficult/Unlikely
├── chain_breaks # What techniques are blocked
└── what_would_help # Suggestions for success
Command Integration
# Full pipeline: scan -> validate -> exploit
/scan ./webapp # Find potential vulns
/validate ./webapp # Confirm they're real
/exploit ./webapp --finding FIND-001 # Develop working exploit
# With specific vulnerability type
/validate ./webapp --vuln-type command_injection
# Validate existing findings
/validate ./webapp --findings scanner-results.json
Benefits of Dual Validation
- No wasted effort on hallucinations - Stage C catches fabricated findings
- No wasted effort on unreachable code - Stage D filters test/dead code
- No wasted effort on impossible exploits - Feasibility catches blocked techniques
- Clear guidance on what WILL work - Both systems provide actionable paths forward
- Documented learning - disproven.json and chain_breaks explain what was tried
Summary
| Layer | Question | When | Output |
|---|---|---|---|
| Exploitability Validation | Is it REAL? | All findings | Validated + PoC |
| Exploit Feasibility | Can we EXPLOIT it? | Memory corruption | Verdict + constraints |
Together, they ensure you only invest exploit development time on vulnerabilities that are both confirmed real and actually exploitable.