9.1 KiB
Fold SAST / DAST / Symbolic Roadmap
Date: 2026-06-02 Scope: roadmap after recent Ghidra/P-Code, gadget, ROP-chain, and vendor-pruning work.
Fold should evolve as a three-lane vulnerability engine rather than one monolithic analyzer. The lanes share reports and provenance, but keep their evidence separate.
Source C/C++ ── Clang AST/CFG ──▶ Source facts ─┐
│
Binary ── LIEF/r2 metadata + Ghidra P-Code ───▶ Binary facts ─┐
▼
Fold fact/graph layer + symbolic obligations
│
▼
Z3 bounded proof / heuristic finding
│
▼
Existing + generalized confirmation layer
confirm runner / libFuzzer+ASan / KLEE / SymCC / angr
Lane 1 — Source SAST
Keep Clang as the source of truth for C/C++ semantics. Detectors should move toward this pipeline:
- cheap AST/fact prefilter;
- graph/data-flow query;
- bounded Z3 proof obligation;
- optional dynamic confirmation.
References:
- Clang Static Analyzer: https://clang.llvm.org/docs/ClangStaticAnalyzer.html
- Clang data-flow analysis intro: https://clang.llvm.org/docs/DataFlowAnalysisIntro.html
- CodeQL C/C++ library/data flow: https://codeql.github.com/docs/codeql-language-guides/codeql-library-for-cpp/
- Code Property Graphs: https://www.ieee-security.org/TC/SP2014/papers/ModelingandDiscoveringVulnerabilitieswithCodePropertyGraphs.pdf
Lane 2 — Binary SAST
Keep binary evidence separate from source evidence.
| Tool | Fold role |
|---|---|
| r2 | fast fallback extraction: functions, strings, xrefs, rough metadata |
| LIEF | stable ELF/PE/Mach-O metadata candidate |
| Ghidra/SLEIGH | binary instruction semantics through raw/high P-Code |
| Capstone | gadget byte-window discovery only; not semantic proof |
References:
- Ghidra P-Code: https://ghidra.re/ghidra_docs/languages/html/pcoderef.html
- Ghidra SLEIGH: https://ghidra.re/ghidra_docs/languages/html/sleigh.html
- LIEF C++ API: https://lief.re/doc/latest/api/cpp/index.html
- radare2 book: https://book.rada.re/intro/overview.html
Lane 3 — DAST / concolic confirmation
Fold already has two concrete confirmation surfaces:
fold confirm: deeper bounded symbolic confirmation for selected findings, with optional SV-COMP GraphML witnesses.fold fuzz prep+fold fuzz run: emitsfindings.predicted.json, compiles libFuzzer/ASan harnesses, matches ASan crashes back toFinding.id, and promotes matching findings toConfidence::ConcreteWitness.
Fold should not become KLEE, angr, or a web scanner. The shipped confirmation
paths now also have a shared machine-readable FindingConfirmationTask /
FindingConfirmationResult model, plus compatibility sidecars for the fuzz path.
The remaining design work is to deepen adapter coverage and attach stable fact
IDs at more detector emission sites.
Suggested schema:
FindingConfirmationTask {
finding_id: string
backend: source | binary | hybrid
lane: clang | ghidra-pcode | r2-heuristic | lief-metadata
target: { file_or_binary, function, source_location?, binary_address? }
input_channel: argv | stdin | file | env | socket | harness | unknown
controlled_values: [name_or_register]
path_predicate: textual-or-SMTLIB summary
hazard: div-by-zero | null-deref | overflow | oob | uaf | taint-sink | rop-reachable
expected_violation: string
suggested_adapter: klee | symcc | libfuzzer | afl | angr | triton | manual
artifacts: [seed, harness, compile_db, binary]
}
Result states should align with Fold's existing confidence model:
syntactic -> heuristic -> proved -> concrete-witness
↘ refuted | timeout | unsupported
ConcreteWitness is already first-class: a SAT-feasible/static finding was run
under ASan/libFuzzer and produced a matching crash. New adapters should preserve
that semantics instead of creating a parallel confidence vocabulary.
KLEE is the next source-confirmation adapter family. A narrow optional prototype
now consumes a FindingConfirmationTask, compiles a source artifact to LLVM
bitcode, runs KLEE when installed, and writes a FindingConfirmationResult.
Absent KLEE skips cleanly. The current smoke path is
tests/confirmation/klee/run_klee_smoke.sh.
References:
- KLEE: https://www.usenix.org/conference/osdi-08/presentation/klee-unassisted-and-automatic-generation-high-coverage-tests-complex
- SymCC: https://www.usenix.org/conference/usenixsecurity20/presentation/poeplau
- S2E: https://dl.acm.org/doi/10.1145/2110356.2110358
- Driller: https://www.ndss-symposium.org/wp-content/uploads/2017/09/driller-augmenting-fuzzing-through-selective-symbolic-execution.pdf
- QSYM: https://www.usenix.org/conference/usenixsecurity18/presentation/yun
- angr: https://docs.angr.io/en/latest/
- Triton: https://triton-library.github.io/
Benchmark plan
| Benchmark | Purpose |
|---|---|
| Juliet C/C++ | source SAST CWE recall/precision |
| SV-COMP | verifier discipline and witness style |
| CGC | binary/concolic exploration |
| Magma | fuzz/DAST reached-vs-triggered bug metrics |
References:
- Juliet/SARD: https://samate.nist.gov/SARD/test-suites/112
- SV-COMP benchmarks: https://sv-comp.sosy-lab.org/2025/benchmarks.php
- Magma: https://hexhive.epfl.ch/magma/
Near-term implementation order
- Harden the current ROP planner correctness issues. Done.
- Guard executable-section extraction by host memory, not fixed byte caps, so gadget scans preserve precision whenever the hardware can support the image. Done.
- Add
FindingConfirmationTaskas a report/schema concept over the existingconfirmandfuzz prep/runpaths. Done: seeinclude/fold/confirm/confirmation_task.hpp. - Add optional KLEE/SymCC/angr adapters that consume the same task schema. KLEE smoke prototype done; SymCC/angr remain open.
- Define stable fact IDs before Souffle. Done for the model: see
include/fold/ir/fact_id.hpp; broader detector emission-site population remains open. - Harden binary P-Code false-positive controls for common libc and guarded-arithmetic cases.
Done for the first curl-derived regressions and follow-up path-order cases: P-Code call
semantics now preserve fortified
_chkwrappers, SSA sink naming trusts raw call-site correlation instead of synthesized target fallbacks, raw div/rem findings are gated by machine division instruction addresses, and bounded forward P-Code path exploration forksCBRANCHtaken/fallthrough paths while stopping local fallthrough on forwardBRANCH/RETURN. A full basic-block CFG with joins remains future precision work.
Status audit — 2026-06-03
Completed or substantially implemented:
- Source, binary, and confirmation lanes remain separate in implementation and report provenance.
- Confirmation task/result schema exists and is used by
confirmandfuzz prep/runsidecars. - KLEE smoke adapter exists and skips cleanly when unavailable.
- Stable fact ID model exists.
- ROP planner/gadget extraction has focused regression coverage.
- Binary P-Code curl-smoke false positives from
memchr/memcpy, fortifiedstrncpy_chk, guardedudiv, taken-target ordering, and branch-skipped fallthrough hazards are covered by unit tests and the/usr/bin/curlsmoke scan. - Latent/precondition evidence is now produced by null/div detector paths, not only serialized in JSON/SARIF.
- Hybrid profile merging preserves lane timing/counter fields, keeping source and binary lanes separately measurable in merge-only hybrid mode.
Future expansion ideas, not required for the current shipped scope:
- SymCC and angr adapters over the shared confirmation task/result schema. The shipped
confirmation lane is already useful with
confirm,fuzz prep/run, and optional KLEE smoke. - Broader fact ID population at additional detector emission sites. The current fact ID model is in place; expanding coverage is incremental provenance work.
- Reproducible benchmark harness scripts for Juliet, SV-COMP, CGC, and Magma. These are evaluation infrastructure, not core feature blockers.
- Full P-Code basic-block CFG/path exploration with join policies. The shipped binary lane now has bounded forward path exploration for observed false positives and block-order regressions; full CFG joins remain a precision upgrade, not a prerequisite.
Guardrails
- Do not route decompiled C from binaries through source detectors.
- Do not let dynamic confirmation erase unconfirmed static findings; report it as a separate state.
- Keep binary metadata, binary semantics, source semantics, and dynamic witnesses separately measurable.
- Every finding and confirmation task must preserve backend/lane provenance.
- Keep
confirmation.tasks.jsonandconfirmation.results.jsonsidecars compatible with legacyfindings.predicted.jsonand augmented findings JSON.