mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
Ran the humanizer rules over 79 prose files in the active specs (brief, design, requirements, research and narrative docs). Removed em dashes, significance inflation, forced rule-of-three, bold-label list items and filler. Skipped tasks.md checklists and the retired specs (harnessx-*, openrouter-sast-harness, unseen-repo-evaluation). Every number, path, command, hash and identifier was preserved: checked each file against HEAD for drift in numbers, inline code and code fences, zero drift across all 79 files. Co-Authored-By: Claude Opus 4.8 <[email protected]>
7.1 KiB
7.1 KiB
Research & Design Decisions
Summary
- Feature:
corpus-seeded-mechanisms - Discovery Scope: Extension of mechanism memory, MAP stage, pair eval, and the improve loop
- Key Findings:
semantic/mechanisms.pyalready hasMechanism,MechanismStore(append-only JSONL),append_mechanism, embedding cache, hard filters by language/CWE/tags, andorder_promotions. It is written only bycli._append_proven_mechanismsafter a sandbox trigger, so it is empty on every real tree.- Clearwing's recall lever is the variant loop: a proven mechanism becomes a structural search over the messy tree. OpenUltraSAST copied the store and the retrieval, not the loop.
FileIRcall sites already carry callee name, argument texts, argument identifier lists, and constant flags; binds carry source text and names. That is enough for a shape without new parsing.- The pair scorer (
pair-corpus-honesty) gives labeled function, mechanism id, provenance, and soon a review tier; the fixed excerpt gives the guard the fix added by diffing statement kinds. - The improve loop has bounded levers with a validator, journal, byte-for-byte revert, and now a per-profile holdout clause; a
mechanismslever fits without changing the gate. - Measured 2026-09-05: vibe-py 13/35, vfc-js 1/16, sast 4/10 achievable. Web classes repeat structurally (request-derived string into
exec/execute, identity from the body,os.path.joinwith a parameter, permissive defaults), which is what a shape search catches.
Research Log
Mechanism store today
- Context: Can the existing store carry corpus-derived records?
- Sources Consulted:
semantic/mechanisms.py,cli.py_append_proven_mechanisms,propose-adjudicate-provedesign §Mechanism. - Findings:
Mechanismfields are summary, cwe, language, tags, keywords, what_made_it_exploitable, source_finding_id, source_repo. Identity is the pattern. JSONL is authoritative; vectors are a rebuildable cache keyed by id and model. - Implications: add
origin(sandbox|corpus),review_tier,pairs,shape(structured),guardas additive fields with defaults so old rows load. A second writer (append_from_pair) beside the sandbox writer.
Shape derivation from FileIR
- Context: Avoid regex and LLM authoring.
- Sources Consulted:
semantic/ir.py(CallSite.arg_names,arg_is_constant,Bind.names,FunctionIR.params),semantic/taint.py(_source_in, parameter seeding). - Findings: for the labeled function, the sink call site is the call whose trailing name equals the label's sink or whose line equals the label's line; source positions are argument indexes whose identifiers trace by binds to a fact source, a parameter, or a container read. Guard kind comes from statements on the fixed side absent on the vulnerable side:
ifwith== NULL/is None/!x→null_test; comparison with<,>,len(→bounds_test; membership in a literal collection orstartswith/regex →allowlist_test; identity read from an auth context (request.state,req.user,session) →auth_check; parameterized second argument →parameterized_call; changed declared type →type_change. - Implications:
semantic/variants.pyimplementsderive_shape(pair_ir_vuln, pair_ir_fixed, label)andmatch_shape(file_ir, shape). Guard classification is heuristic and closed; unknown →none.
Where variant search sits
- Context: Propose, adjudicate, prove roles must stay separate.
- Sources Consulted:
three-stage-scandesign (MAP stage, hunter suspicion),propose-adjudicate-prove(overlay records, coverage),regress/candidate.py. - Findings: MAP already runs overlay and the tool hunter; variant search is a third proposer that reads
FileIRand the store. Findings atsuspicion, originvariant; when the overlay has a flow at that call site, merge (attach mechanism id to the overlay record). Candidate eligibility follows the hunter-eligibility path being added inreachability-flow-modelor the sev-5 forced-hotspot path today. - Implications: no disposition change; one new finding origin; manifest counters.
Leave-one-out
- Context: Prove that corpus growth raises recall, honestly.
- Findings: pair eval materializes each side into a temp tree already; a leave-one-out runner seeds a temp store from the other trusted pairs and runs variant search on both sides, scoring with the pair scorer's detection and leak rules.
- Implications:
pairs.pygains a read-only consumer path (evaluate_loo) or a sibling modulesemantic/loo.pyto keep the scorer's boundary; report per slice, profile, mechanism; artifact only.
Architecture Pattern Evaluation
| Option | Description | Strengths | Risks / Limitations | Notes |
|---|---|---|---|---|
| Embedding retrieval only | Rank existing promotions by mechanism similarity | Already exists | Cannot propose anything new; store empty | Rejected as recall lever |
| LLM writes Semgrep rules from pairs | Model authors patterns | Flexible | Unbounded pattern text, unverifiable, violates no-model-authored-patterns | Rejected |
| Structural shapes from FileIR plus variant search | Closed shape vocabulary, deterministic match | Zero-dep, bounded, testable leave-one-out | Shapes coarse; guard heuristics | Selected |
| Fine-tuned classifier on pairs | ML detector | Learns anything | Opaque, no fix guidance, data too small | Rejected |
Design Decisions
Decision: Seed only from seeded and reviewed tiers
- Context:
titlepairs are unreviewed guesses;advisorypairs have correct fixes but unlabeled mechanisms. - Selected Approach: export reads
review_tier;advisory/titlemay be scored leave-one-out as held-out targets but never seed. - Trade-offs: fewer seeds at first; honest about what the detector was taught.
Decision: Variant is a proposer at suspicion
- Context: Evidence honesty.
- Selected Approach: origin
variant,suspicion; merge with overlay flow when present; sandbox may raise. - Trade-offs: variant-only hits do not fail CI; correct.
Decision: Lever admits records, not shapes
- Context: Keep the validator closed.
- Selected Approach:
mechanismslever edits reference record ids produced by the exporter; free-form shapes are rejected.
Risks & Mitigations
- Coarse shapes over-match (
exec(x)everywhere): source-position requirement plus fact/parameter/container check; report leak rate on fixed sides leave-one-out; the per-profile gate rejects admissions that leak. - Guard heuristics misclassify: closed set with
none; reported, not used for demotion. - Store growth: dedupe by shape; one record per shape with pair provenance list.
- Leave-one-out cost: one temp store per pair over tens of pairs; fine; cache parsed IR per excerpt.
References
semantic/mechanisms.py,semantic/ir.py,semantic/taint.py.kiro/specs/propose-adjudicate-prove/design.md§Mechanism (Clearwing reference architecture).kiro/specs/pair-corpus-honesty/(review tiers, pointer slices, scorer rules).kiro/specs/harnessx-self-improving-rulesets/design.md(bounded levers, accept gate)- Clearwing sourcehunt mechanism memory and variant loop (reference, not a dependency)