- skills/fold-sast: rename to skill-fold-sast and expand the scan/precision guidance for C++/Rust/Swift lanes - docs/architecture: record call-graph phase decomposition and the optimization-loop TP/FP/TN/FN evidence policy - docs/mcp-tools + README: update budget/per-query defaults (1800s/6000ms) and note the OpenGrep pre-push hook
24 KiB
| name | description | tags | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| skill-fold-sast | Fold bounded symbolic SAST / binary-analysis / confirmation guide for C++, Rust, and Swift code review, scanning, precision measurement, and optimization. Use when selecting a Fold scan mode, interpreting findings, profiling a scan, or confirming a suspected vulnerability. |
|
Fold — Bounded Symbolic SAST, Binary Analysis, and Confirmation
Overview
Fold analyzes source and binaries while keeping evidence lanes separate:
- Source lane: Clang LibTooling, normalized IR/summaries, bounded Z3-backed detectors, and SARIF/versioned-findings-JSON/Markdown reporting.
- Binary lane: radare2-backed metadata/heuristics, Ghidra/SLEIGH P-Code semantics, Capstone gadget discovery, and candidate ROP evidence.
- Confirmation lane: shared
FindingConfirmationTask/FindingConfirmationResultrecords used byfold confirm,fold fuzz prep,fold fuzz run, and optional adapters such as the KLEE smoke prototype.
Use this skill when working on the Fold codebase, running scans, adding observers or detectors, interpreting findings, updating CLI/report behavior, or comparing Fold against CSA, CodeQL, Infer, CBMC, Semgrep, clang-tidy, KLEE, angr, or concolic/fuzzing tools.
When to use
Use this skill when:
- working in the Fold repository;
- reviewing or scanning a C++, Rust, or Swift project with Fold;
- running
fold scanwithsource,binary,hybrid,rust,swift, orautomode; - adding or modifying detectors, observers, summaries, binary heuristics, or report serialization;
- interpreting confidence levels, counterexamples, fix-its, fuzz witnesses, binary exploit context, or fact provenance;
- preparing or running confirmation with
fold confirmorfold fuzz prep/run; - using optional confirmation experiments such as KLEE smoke tests;
- updating CLI help, embedded skills, MCP surfaces, or docs.
When project input is available, run the appropriate scan rather than merely suggesting a command. Stop and state the missing prerequisite when a compile database, Rust crate, Swift source/package, binary, benchmark corpus, baseline, or precision oracle is absent.
When not to use
Do not use this skill for generic static-analysis tool selection with no Fold work, Semgrep rule authoring, variant hunting without a Fold seed finding, or a one-off Z3/SMT question unrelated to Fold.
Architecture
source / binary / rust / swift input
↓
scan router ── keeps source, binary, and language lanes separate
↓
frontend / binary extractor → IR, summaries, P-Code, facts
↓
detectors / observers → findings + evidence + provenance
↓
SARIF / findings-json / Markdown + optional confirmation tasks/results
↓
fold confirm / fold fuzz / optional KLEE-style adapters
Module boundaries
| Module | Typical files | Responsibility |
|---|---|---|
| CLI/router | src/cli/, include/fold/cli/ |
commands, scan routing, confirm/fuzz orchestration |
| frontend | include/fold/frontend/, src/frontend/ |
Clang/Rust/Swift input collection |
| binary | include/fold/binary/, src/binary/ |
r2, Ghidra P-Code, Capstone gadgets, ROP candidates |
| ir | include/fold/ir/, src/ir/ |
expression/summary/fact identity models |
| symbolic | include/fold/symbolic/, src/symbolic/ |
Z3 encoding, observers, bounded proof |
| detect | include/fold/detect/, src/detect/ |
finding-class detectors |
| confirm | include/fold/confirm/, src/confirm/ |
shared confirmation task/result schema |
| fuzz | include/fold/fuzz/, src/fuzz/ |
harnesses, seeds, witness matching |
| report | include/fold/report/, src/report/ |
finding model, SARIF/Markdown/JSON |
| mcp/lsp | include/fold/mcp/, include/fold/lsp/ |
agent/server integrations |
Evidence lanes and boundaries
- Keep source and binary backends separate unless router work explicitly asks for hybrid orchestration.
- Binary findings are heuristic unless source/Z3 or runtime confirmation corroborates them.
- ROP chains are candidate exploitability evidence; preserve caveats such as ASLR/PIE/canary/frame layout and input-control assumptions.
- Hybrid mode should preserve per-finding backend provenance and avoid silently hiding source coverage unless the user requested a capped candidate set.
--detectors production-reachabilityis a serial whole-project pass. Treat unknown guards and incomplete roots/dispatch as reachable; only complete closed-worldunreachable-productionevidence may setremoval_candidate.compile-variant-absentrequires an explicit finite variant manifest.
Confidence model
| Confidence | Meaning |
|---|---|
concrete-witness |
Runtime confirmation, typically libFuzzer/ASan, observed a matching crash. Strictly strongest tier. |
proved |
Z3 established the condition under Fold's bounded model. |
latent |
The bounded proof depends on a caller/environment precondition that is not discharged locally. |
heuristic |
Evidence is partial, approximate, binary-heuristic, or unsupported constructs were involved. |
syntactic |
Structural/hash/shape match only; no semantic proof. |
Treat Fold as a bounded model. proved means proved within the model and
budget, not universal program correctness. Prioritize concrete-witness, then
proved, then latent findings whose preconditions are realistic, followed by
high-impact heuristic findings.
Detectors
Source/security examples
| Detector | Hazard |
|---|---|
div-by-zero |
divisor may be zero under path |
null-deref |
pointer/member dereference may be null |
int-overflow |
integer arithmetic may overflow at source width where modeled |
int-truncation |
narrowing conversion may lose information |
sign-conversion |
signed/unsigned conversion may change meaning |
oob |
index/buffer access may be out of bounds |
taint-track |
untrusted source reaches sensitive sink |
uninit-read |
local/object read may be uninitialized |
use-after-move |
C++ object use after move |
iterator-invalidation |
iterator may be used after invalidating operation |
always-condition, unreachable |
symbolic control-flow anomalies |
Redundancy examples
| Detector | Hazard |
|---|---|
clone |
Type-2/3 structural clone candidates |
equiv |
semantic equivalence under bounded Z3 encoding |
dead |
dead branch/path predicate evidence |
class-dup |
class/method duplication candidates |
Binary examples
Binary mode can report hardcoded strings/credentials, unsafe calls, suspicious sections/imports/symbols, P-Code summaries, buffer-overflow-like evidence, gadget/ROP context, and other backend-specific heuristic findings depending on build options and available tools.
CLI recipes
Source scan
fold scan --mode source --compile-db build/compile_commands.json \
--detectors div-by-zero,null-deref,int-overflow,oob,taint-track \
--format sarif --output fold.sarif \
--budget-seconds 300 --per-query-ms 2000 --processes 0
For native machine-readable output, use the explicitly versioned envelope:
fold scan --mode source --compile-db build/compile_commands.json \
--detectors security --format findings-json --output fold-findings.json
Binary scan
fold scan --mode binary --binary ./app --detectors security \
--binary-max-functions 0 --format sarif --output fold-binary.sarif
Hybrid scan
fold scan --mode hybrid --compile-db build/compile_commands.json \
--binary ./app \
--hybrid-strategy merge-only --detectors security \
--format sarif --output fold-hybrid.sarif
Rust or Swift source scan
fold scan --mode rust path/to/crate --detectors rust-security \
--format sarif --output fold-rust.sarif
fold scan --mode swift path/to/file.swift --detectors swift-security \
--format sarif --output fold-swift.sarif
Rust and Swift source findings are heuristic today; use binary mode for compiled artifacts when binary evidence is desired.
Rust complexity scan
fold scan --mode rust path/to/crate --detectors complexity \
--complexity-threshold 15 --format sarif --output fold-rust.sarif
The Rust frontend evaluates complexity from HIR control-flow structure. Keep
the threshold explicit in reproducible runs; it is shared with the C++ detector.
Code-review and scan workflow
Use the installed CLI as the authority for the current release before forming a command. Normal help shows stable options; advanced help exposes tuning, profiling, cache, and watchdog controls:
fold scan --help
fold scan --advanced-help
1. Select the lane explicitly
| Review input | Command shape | Rules |
|---|---|---|
C++ project with compile_commands.json |
fold scan --mode source --compile-db <db> ... |
Use --scope security for security review, --scope quality for maintainability, or compose both. |
| One or more C++ files without a database | fold scan --mode source <paths...> ... |
Fold infers a synthetic compile database; pass --std and required --extra-arg flags explicitly. |
| Cargo crate or Rust file | fold scan --mode rust <crate-or-file> --detectors rust-security ... |
Do not pass --rust-allow-build-code for untrusted projects; it enables build scripts and proc macros. |
| Swift package or source file | fold scan --mode swift <package-or-file> --detectors swift-security ... |
Keep Swift reports and provenance separate from source C++ or binary evidence. |
| Executable or firmware only | fold scan --mode binary --binary <path> ... |
Binary results are heuristic unless independently corroborated. |
| Matching source and binary inputs | fold scan --mode hybrid --compile-db <db> --binary <path> --hybrid-strategy merge-only ... |
merge-only is the only implemented strategy. It must not hide source coverage. |
Use --mode auto only for exploratory work. Reproducible reviews and benchmark
artifacts use an explicit mode, detector/scope selection, and file output.
--input-type and --format json are compatibility aliases; do not use them
in new commands.
2. Run the smallest complete review
Write reports to files so the original evidence remains available:
fold scan --mode source --compile-db build/compile_commands.json \
--scope security,quality --format sarif --output fold-review.sarif
fold grep "overflow" fold-review.sarif --field message \
--backend source --actionable-only --format json --output overflow-findings.json
Use findings-json instead of SARIF only when a consumer requires Fold's
native versioned envelope. fold grep searches existing Fold reports; it does
not scan source text.
For a Fold repository change, run the local quality gate after the focused scan:
fold quality --compile-db build/release/compile_commands.json
Do not invoke fold quality with missing project prerequisites or suppress its
policy/test failures to obtain a scan result.
3. Review findings by evidence
- Preserve the SARIF or findings-json report, profile, and logs.
- Group findings by backend, rule, confidence, and stable ID.
- Treat
concrete-witnessas runtime evidence;provedis bounded-model evidence;latent,heuristic, andsyntacticrequire progressively more source and contract review. - Verify a suspected vulnerability with
fp-checkbefore calling it actionable. Trace callers, guards, API contracts, and the exact sink. - Suppress generated or third-party findings through
--exclude-globor a reviewed suppression file, never by editing the scanned dependency.
Precision and optimization workflow
Use this workflow only when the request involves performance, memory, false-positive reduction, precision claims, or benchmark changes.
- Measure first. Use a checked-in project manifest with
scripts/benchmarks/run_project_eval.py; preserve the immutable run artifacts, profile, target-set fingerprint, configuration fingerprint, and revision. Usescripts/benchmarks/run_optimization_harness.pyfor a compact project artifact. - Attribute the owner. Select one ranked detector, source phase, graph subphase, reliability failure, or focused microbenchmark. Do not optimize an unattributed aggregate wall-time bucket.
- Use the required specialist skill. Invoke
cpp-performancefor a profiling decision; invokepaperbridgebefore a research-backed algorithm change; invokefp-checkfor each suspected production vulnerability. - State the invariant. Behavior-preserving changes retain finding identity, source/binary provenance, operational coverage, and expected positive cases. A precision change names its expected identity delta before implementation.
- Require labels for precision claims. TP, FP, FN, and TN require explicit positive and clean-negative oracle cases. A reviewed production alert sample is not a recall benchmark, and absent TN/FN values must remain unmeasured.
- Run an ablation. Keep a default-on change only when the profiled owner improves beyond observed variance without unexpected coverage, identity, reliability, or RSS regression. Retain a useful unproven strategy as default-off; reject non-reproducible or unattributed wins.
Follow docs/architecture/optimization-loop.md when working in the Fold
repository. It defines the full experiment record and validation matrix. Keep
source, binary, and hybrid results as separate lanes unless router work
explicitly changes merge-only orchestration.
Deeper bounded symbolic confirmation
fold confirm build/compile_commands.json --rule null-deref --unwind 10 \
--budget 5000 --output confirm.json --witness witnesses/
Runtime confirmation with libFuzzer + ASan
fold fuzz prep --compile-db build/compile_commands.json --output /tmp/fold-fuzz
fold fuzz run --prep-dir /tmp/fold-fuzz --report /tmp/fold-fuzz/augmented.json
fold fuzz prep preserves legacy findings.predicted.json and also writes
confirmation.tasks.json. fold fuzz run writes augmented findings and
confirmation.results.json. Matched crashes promote findings to
concrete-witness.
Query existing Fold findings
fold grep searches Fold SARIF or native findings-json reports, not raw source
text. It uses bounded fixed-string matching and preserves finding IDs and backend
provenance.
fold grep "null pointer" fold.sarif --field message --ignore-case
fold grep "fold.null-deref" fold.sarif --field rule \
--backend source --path-glob 'src/*.cpp' --actionable-only
fold grep "token" source.sarif binary.sarif \
--format json --output matches.json
Searchable fields are message, id, rule, path, function, and
evidence. Typed filters include rule, confidence, backend, path glob, baseline
status, suppression, and actionable-only. JSON query output includes deterministic
pagination and truncation metadata.
MCP scan and query lifecycle
Use the canonical tools fold.scan, fold.scan_start, fold.scan_status,
fold.scan_jobs, fold.scan_job_findings, fold.scan_activate,
fold.get_scan_context, fold.get_findings, fold.query_findings,
fold.suggest_merge, and fold.explain.
For long scans, call fold.scan_start, poll fold.scan_status, then query the
completed job_id with fold.query_findings or activate it with
fold.scan_activate. MCP accepts paths only under configured --allow-root
roots and enforces server-owned queue, process, solver-budget, path-count, and
work-item limits before execution. Deprecated tool/argument aliases remain
callable but hidden and return structured deprecation metadata; do not use them
in new recipes.
Embedded skill output
fold skill # print this embedded SKILL.md
fold skill -o SKILL.md # write it to a file
fold --help # shows the skill command for agents
Long-running scans in Pi
Use MonitorCreate for large scans instead of blocking inline:
MonitorCreate(command="fold scan --compile-db ... --format sarif "
"--output /tmp/fold/results.sarif ...",
description="Fold scan", timeout=600000,
onDone="Parse the Fold results and summarize findings")
Key flags
--mode:auto,source,binary,hybrid,rust, orswift.--compile-db: path tocompile_commands.jsonor a build directory.--binary: binary/firmware path for binary or hybrid mode.--detectors: repeatable or comma-separated detector list.--source-detectors/--binary-detectors: backend-specific hybrid overrides.--format:sarif, versioned nativefindings-json, ormarkdown/md.jsonis a deprecated compatibility alias for SARIF.--fix-output: write a unified diff for available FixIts; no in-place edits.--exclude-glob: repeatable file exclusion patterns. Project-relative patterns such asthird_party/**also match absolute compile-database paths at a path component boundary.--budget-seconds,--per-query-ms,--loop-unroll: symbolic budgets.--processes 0: auto worker count.1means one isolated worker for ordinary source scans, not in-process execution; profile and incremental scans currently use the serial in-process path because their state is not worker-mergeable.--incremental+--cache-dir: changed-function/caller reruns.--config-profile: strict v1 runtime assumptions and explicit production entrypoints for privacy-safe guarded callsite/root evidence; source/hybrid only, and discovery alone does not prune graph edges.--portfolio: SMT plus bit-blast SAT portfolio for QF_BV queries.--nullable-allocations: model allocations as nullable for null-deref.--suppressions,--baseline,--quarantine-dir,--per-tu-timeout: operational stability and triage controls.--profile,--profile-output,--profile-solver,--profile-reach,--trace: diagnostics. Supplying--profile-outputenables profiling; report and profile paths must be distinct.--advanced-help: print the catalog-generated tuning/profile/cache options omitted from normal scan help.
New automation should use canonical spellings. Compatibility aliases such as
--input-type, scan --format json, hidden MCP tool names, and hidden MCP
argument aliases remain callable only for migration. They are omitted from
normal help/schema documentation and emit deprecation details. Fold 1.0.0 is the
earliest eligible—not automatic—removal boundary; see docs/compatibility.md.
Project evaluation and profiles
Use the manifest-driven runner for repeatable evaluation of a real source, Rust, or binary project. Manifests pin the corpus, lane, detector scope, limits, and stability/performance budgets; do not check in a generated baseline before reviewing it.
python3 scripts/benchmarks/run_project_eval.py \
--manifest tests/benchmarks/projects/yams_source.json
python3 scripts/benchmarks/run_project_eval.py \
--manifest tests/benchmarks/projects/sage_rust.json
For Rust projects with a pinned toolchain, put the toolchain in the manifest so
the fold-rust child process receives it. The runner writes SARIF, profile
JSON, logs, immutable run artifacts, finding-stability data, and an optional
gold/disposition/performance comparison.
Use --profile-output when inspecting a scan. Requested report/profile files
are written through sibling temporary files and atomically renamed; an
open/write/rename failure returns exit 2. Console actionability, exit status,
FixIts, SARIF, and native JSON derive from one filtered/deduplicated finding set.
Profiles expose findings_before_filter and findings_report_visible so count
changes remain explainable. Source profiles report solver metrics; Rust and
Swift profiles report frontend extraction plus ingestion/IR rows; binary
profiles report heuristic, BinaryIR, and P-Code rows. P-Code solver statistics
remain separate from source solver statistics.
Check fold --version before retaining evidence. Development builds report the
Meson semantic version plus Git revision and a .dirty suffix when configured
from a modified tree. The same provenance is written to SARIF, native JSON,
profile JSON, and benchmark run artifacts.
Interpreting findings
- Group by detector/rule and confidence.
- Prioritize
concrete-witnessandprovedsecurity findings. - Read counterexamples, path predicates, witness metadata, and backend evidence.
- For heuristic findings, identify the approximation: unresolved calls, unknown lengths, unsupported control flow, partial binary metadata, or missing interprocedural summaries. Invalid sink-model argument indexes and unsupported portfolio expressions fail closed with bounded diagnostics; they are not findings.
- De-duplicate repeated findings by finding ID /
ruleId:file:line:col. - Exclude generated/vendor code with
--exclude-globor suppressions rather than editing third-party sources. Missing generated dependencies, frontend exits, TU timeouts, and worker signals are coverage failures, not findings; preserve their logs and quarantine provenance. - Preserve complete SARIF or findings-json artifacts for machine triage; summarize only bounded actionable findings to users.
Confirmation and fact identity
FindingConfirmationTaskis the shared adapter input.FindingConfirmationResultis the shared adapter output.- Fuzz prediction compatibility remains: old consumers can still read
findings.predicted.json. - Optional fact provenance can link findings/tasks to cross-lane identities such as functions, blocks, operations, and values. Do not duplicate wire-format key strings; centralize JSON keys in the owning C++ header/source.
Development workflow
Read AGENTS.md before router/backend work. Keep source and binary paths
separate. For complex detector or backend changes, write focused tests first
where practical.
Focused validation:
ninja -C build/release
meson test -C build/release fold:scan_e2e fold:cli_paths fold:mcp_stdio --print-errorlogs
meson test -C build/release fold:confirm_cli --print-errorlogs
meson test -C build/release fold:fuzz_prep fold:fuzz_run --print-errorlogs
meson test -C build/release fold:confirmation_task fold:fact_id --print-errorlogs
git diff --check
Binary/ROP validation:
meson test -C build/release \
fold:binary_backend fold:gadget_capstone fold:gadget_semantics \
fold:rop_chain \
--print-errorlogs
Optional KLEE smoke:
tests/confirmation/klee/run_klee_smoke.sh
It skips cleanly when KLEE is absent.
Full validation for CLI/router/backend changes:
ninja -C build/release
meson test -C build/release --print-errorlogs
git diff --check
Evaluation-runner changes also require:
python3 tests/benchmarks/test_fold_eval.py
python3 scripts/benchmarks/run_rust_swift_goldens.py
Companion skills
| Skill | Use for |
|---|---|
cpp-review |
Mandatory for C++ code-review requests; covers API safety, UB, and C++ correctness. |
rust-style |
Mandatory for Rust code-review requests; applies Rust-specific idioms and boundaries. |
cpp-performance |
Mandatory when profiling or selecting a C++ performance optimization. |
fp-check |
Mandatory before classifying a suspected vulnerability as actionable. |
paperbridge |
Mandatory for literature-backed optimization or analysis-design proposals. |
static-analysis |
General SAST tooling, CodeQL/Semgrep/SARIF triage |
variant-analysis |
Bug-variant hunting after a seed finding |
semgrep-rule-creator |
Writing Semgrep rules |
cpp-meson-ninja-conan |
Meson/Ninja/Conan C++ build work |
radare2-reversing |
Manual radare2 binary analysis |