Skip to content

SCOUT v2.7.2 — Phase 2C++ detection engine integrity patch

Latest

Choose a tag to compare

@R00T-Kim R00T-Kim released this 24 Apr 05:21
· 9 commits to main since this release

Closes two follow-ups from the v2.4.0 external review (docs/upgrade_plz.md) that had been partially addressed by v2.4.1 but left cosmetic residues in the tree. No pair-eval scorecard movement expected — v2.7.1's 2/5 PASS remains the figure of record.

Changed

Phase 2C++.1 — DECOMPILED_COLOCATED_CAP = 0.45 promoted to a named constant (9488b8b)

The decompiled_colocated taint method previously hardcoded a 0.50 ceiling inline. confidence_caps.py now exposes a 5-tier cap ladder:

Cap Value Evidence level
SYMBOL_COOCCURRENCE_CAP 0.40 Symbols co-occur; no code path confirmed
DECOMPILED_COLOCATED_CAP 0.45 (new) Body-text co-occurrence; inline CALLs visible
STATIC_CODE_VERIFIED_CAP 0.55 Decompiled code inspected + LLM taint trace
STATIC_ONLY_CAP 0.60 Static-reference observation ceiling
PCODE_VERIFIED_CAP 0.75 P-code SSA dataflow confirmed

Consumer impact: decompiled_colocated traces drop 0.50 → 0.45 (-0.05). ROC thresholds previously pinned at 0.50 should be retuned to 0.45 to preserve pre-v2.7.1 recall on that evidence class. priority_score weights and cve_scan's STATIC_CODE_VERIFIED_CAP=0.55 unchanged.

Fixed

Phase 2C++.2 — legacy addr_diff > 16 residues removed (36ea517)

Commit 3352783 (v2.4.1, 2026-04-11, 41 minutes after the v2.4.0 P-code taint engine landed) replaced the primary CALL-matching path with callee-name resolution, but left two residues:

  1. src/aiedge/ghidra_analysis.py — a standalone trace_pcode_forward() helper inside _PYGHIDRA_SCRIPT with its own diff > 16 gate. Never invoked (the inline Strategy 1 loop at line 525-587 has always been the real path).
  2. src/aiedge/ghidra_scripts/pcode_taint.py — an else: addr_diff = abs(...) fallback guarded by if source_api_name:. run() always passes source_api_name=source_api (line 291-294), so the fallback was unreachable at runtime.

Both are now physically removed. _trace_forward_pcode()'s source_api_name parameter is required (no default), formalising the invariant that has held for 13 days. No runtime behaviour change — the production paths have done callee-name matching since v2.4.1.

New guard-rail tests in tests/test_ghidra_dead_code_removed.py pin the removal so grep-based review no longer finds a false-positive match for the offset heuristic.

Why no re-measurement

  • Gap B was runtime-effective since v2.4.1.
  • Gap C's new ceiling only binds on decompiled_colocated, which is emitted solely by the pyghidra fallback (ghidra_analysis.py:609). Environments with Ghidra 12 + analyzeHeadless on PATH exercise the primary script path and rarely hit the fallback.
  • Gate 1/2/3 FAIL is driven by findings.py's single-synthesis selection bottleneck — a 0.05 shift on a rarely-emitted method cannot cross those thresholds.

The full rationale, including git-blame trace and the deferred Gap A (interprocedural taint) decision point, is in docs/v2.7.2_release_plan.md.

Verification

  • pytest -q full regression green
  • ruff check src/ tests/ clean
  • pyright src/ 0 errors
  • scripts/check_doc_consistency.py OK

Pivot Option D unchanged

v2.7.2 is a half-day hygiene release, not a behavioural pivot. The compliance_report stage and four standard mappings shipped in v2.7.0 are unchanged. Phase 3'.2 CRA Audit SaaS v0.0 internal alpha still starts in 2026-05.