Skip to main content

Overview

The exploitability validation pipeline ensures security findings are not false positives by systematically verifying they are real, reachable, and exploitable through a 6-stage process.

Why Validation?

Static analysis tools produce many findings, but not all are exploitable:
  • Hallucinated findings: File doesn’t exist, code doesn’t match scanner output
  • Unreachable code: Dead code, test-only functions
  • Protected paths: Effective sanitization, impossible preconditions
  • Binary constraints: Mitigations that block exploitation
Validation prevents wasted effort on false positives.

The 6-Stage Pipeline

Stage 0: Inventory

Purpose: Build a complete checklist of all code to be analyzed.

Output

checklist.json - Complete function inventory:

Execution

Stage A: One-Shot Analysis

Purpose: Quick exploitability assessment with PoC attempts.

Gates Applied

  • GATE-1 [ASSUME-EXPLOIT]: Assume findings are exploitable until proven otherwise
  • GATE-4 [NO-HEDGING]: No “maybe” or “could be” - verify all claims
  • GATE-6 [PROOF]: Provide concrete proof and vulnerable code

Output

findings.json - Initial exploitability assessment:

Status Values

  • poc_success - PoC successfully demonstrated vulnerability
  • not_disproven - Cannot rule out, needs deeper analysis (Stage B)
  • disproven - Proven safe, no further analysis needed

Stage B: Process

Purpose: Systematic analysis for “not_disproven” findings using attack trees and knowledge graphs.

Gates Applied

ALL gates (1-6):
  • GATE-1: Assume exploitable
  • GATE-2: Strictly follow instructions
  • GATE-3: Update checklist, collect evidence
  • GATE-4: No hedging
  • GATE-5: Full code coverage
  • GATE-6: Provide proof

Working Documents

Stage B creates 5 specialized documents:

1. attack-tree.json

Knowledge graph of attack paths:

2. hypotheses.json

Testable predictions:

3. disproven.json

Failed approaches:

4. attack-paths.json

Attempted exploitation paths with PROXIMITY scoring:
PROXIMITY Scale:
  • 10 - Working exploit
  • 8-9 - Very close, minor obstacles
  • 6-7 - Feasible path, some blockers
  • 4-5 - Significant obstacles
  • 1-3 - Far from exploitation
  • 0 - Not viable

5. attack-surface.json

Sources, sinks, and trust boundaries:

Stage C: Sanity Check

Purpose: Verify findings against actual source code.

Gates Applied

  • GATE-3 [CHECKLIST]: Update checklist with verification
  • GATE-5 [FULL-COVERAGE]: Check all code, no sampling
  • GATE-6 [PROOF]: Show actual code verbatim

Verification Checks

  1. File exists at stated path
  2. Code matches VERBATIM at stated line (not paraphrased)
  3. Source→sink flow is real (not hypothetical)
  4. Code is reachable (function is actually called)

Output

findings.json with sanity_check field added:

Stage D: Ruling

Purpose: Make final exploitability determination based on all evidence.

Gates Applied

  • GATE-3 [CHECKLIST]: Document ruling decisions
  • GATE-5 [FULL-COVERAGE]: Rule on all findings
  • GATE-6 [PROOF]: Justify ruling with evidence

Ruling Criteria

Findings are ruled_out if:
  • Failed sanity check
  • Requires impossible preconditions
  • Protected by effective mitigations
  • Attack paths have PROXIMITY ≤ 2
Findings are confirmed if:
  • Passed sanity check
  • Realistic exploitation path exists
  • No effective protections
  • Attack paths have PROXIMITY ≥ 6

Output

findings.json with ruling field:

Status Values

  • Confirmed - Exploitable, proceed to Stage E
  • Ruled Out - Not exploitable, stop here

Stage E: Feasibility

Purpose: Binary constraint analysis for memory corruption vulnerabilities.
Scope: Stage E only applies to memory corruption types (buffer overflow, format string, UAF, etc.). Web/injection vulnerabilities stop at Stage D.

Memory Corruption Types

Stage E applies to:
  • buffer_overflow
  • heap_overflow
  • stack_overflow
  • format_string
  • use_after_free
  • double_free
  • integer_overflow
  • out_of_bounds_read
  • out_of_bounds_write

Binary Analysis

Integrates with packages/exploit_feasibility for:
  1. Protection detection: ASLR, DEP, RELRO, stack canaries
  2. Constraint analysis: Bad bytes, null terminators
  3. Gadget availability: ROP gadgets, syscall availability
  4. Verdict: Likely / Difficult / Unlikely

Execution

Output

findings.json with feasibility and final_status:

Final Status Mapping

CLI Usage

Full Pipeline

Run complete validation from scratch:

With Pre-existing Findings

Validate findings from scanner output (skips Stage 0 and A):

With Binary for Stage E

Skip Stage E

Custom Working Directory

Python API

Orchestrator

Convenience Function

SARIF Input Support

The validation pipeline automatically converts SARIF format:

SARIF Conversion

  • Rule ID normalization: engine.semgrep.rules.crypto.weak-hashweak_hash
  • CWE mapping: CWE-89sql_injection
  • Deduplication: By file:line:vuln_type
  • Logical locations: Extracts function names
  • Severity mapping: SARIF levels → internal severity

Validation Report

Final output: validation-report.md

Output Style Guide

Per RAPTOR’s style conventions:

Human-Readable Status

  • Exploitable (not EXPLOITABLE)
  • Confirmed (not CONFIRMED)
  • Ruled Out (not RULED_OUT)
  • Proven / Disproven (not PROVEN / DISPROVEN)

No Colored Indicators

  • ❌ Don’t use: 🔴/🟢 (perspective-dependent)
  • ✅ Use: Plain text or ### Exploitable (7 findings)
  • ✅ Other emojis OK: ⚠️, ✓, etc.

Best Practices

Start with SARIF input: Feed scanner output directly to validation to avoid manual finding transcription. The pipeline auto-converts and deduplicates.
Stage B is intensive: For large codebases with many “not_disproven” findings, Stage B can take hours. Consider filtering to high-severity findings first.
Stage E requires binary: If no compiled binary is available, Stage E is skipped. Memory corruption findings will be marked Confirmed without feasibility analysis.

Troubleshooting

Stage A produces all “not_disproven”

This is normal for complex vulnerabilities. Stage B will analyze them systematically.

Stage C sanity checks fail

Common causes:
  • Scanner output has stale file paths
  • Code changed since scanning
  • Scanner hallucinated the finding
Fix: Re-run scanner on current codebase.

Stage E skipped unexpectedly

Check:
  • Binary path is correct: --binary /path/to/binary
  • Binary is executable: chmod +x /path/to/binary
  • Vulnerability type is memory corruption

Integration Examples

From Semgrep

From CodeQL

From Autonomous Mode

Validation runs automatically in /agentic:

See Also