Secure Code Review Harnesses

Module S06 · Course 2A

75 min · Layered Pipeline · False Positive Triage · Semantic Memory · Autofix Gate

Prerequisite: S00–S05

S06.1 — Code Review Harness Architecture

Input: PR diff, full file, repo snapshot, or commit hook. Output: structured findings — file, line, CWE, severity, confidence, remediation.

A layered pipeline. Each layer has a job. No single layer is trusted alone.

The layered pipeline

1. AST parsing — syntax tree, symbol resolution
2. Semgrep — fast pattern rules, high recall
3. CodeQL — deep data-flow, taint tracking
4. LLM semantic — context-aware judgement, FP triage
5. Synthesis — dedup, normalize, score, route

Deterministic first, LLM last. Scanners give recall; the LLM gives precision.

Why deterministic first, LLM last

LLM-first scanning is slow, expensive, inconsistent, and hallucination-prone. The LLM's strength is judgement on a small bounded set — not brute-force scanning.

By the time the LLM sees a finding, the deterministic layers have established the pattern matches. The LLM answers: is this exploitable HERE?

Routing: block / queue / comment

SeverityConfidenceAction
Critical/HighHighBlock PR (status check fails)
Critical/HighMediumQueue for human; inline comment
Medium/LowHighAuto-comment inline
AnyLowFile silently; no PR noise

Over-blocking trains developers to click override without reading.

S06.2 — The False Positive Problem

Semgrep + CodeQL are recall machines. On a large codebase: ~95% recall, ~40% precision. Surface raw output and developers mute the bot within a week.

LLM-powered triage

Per finding: pass code + surrounding function + cross-file context. Ask: reachable from untrusted data? sanitized? true or false positive?

The model does not FIND the vulnerability — the scanner did. The model JUDGES it. Same reader/actor separation as S01.3, S02.4.

The feedback loop

Human marks finding FP or confirms TP
Verdict stored in vector index (feedback store)
Next triage: similar findings retrieved as few-shot examples
Precision on that finding class improves over weeks

This is the loop that turns a static ruleset into a learning harness.

Measuring the harness

~92% / ~85%

Precision / Recall target after LLM triage (vs ~40% / ~95% raw).

StagePrecisionRecall
Raw Semgrep~40%~95%
After LLM triage~92%~85%

Dataset: OWASP Benchmark, Juliet, DVWA, or your own labeled history.

S06.3 — Semantic Codebase Memory

Single-file analysis misses cross-file vulns. Taint enters in handler.py, sink executes in repository.py. No single-file scan sees the flow.

Function-level indexing

Each function embedded with metadata: file, symbol, callers, callees, source. Vector DB with a static call graph overlay.

For a finding at X:Y, retrieve: enclosing function, all callers (source), all callees (sink), sanitizer-like functions.

Retrieval = graph traversal (call graph) + semantic search (vector similarity).

Context budget

Retrieved context cannot all fit. Enforce a token budget (4k–8k). Prioritize: direct callers/callees > sanitizers > transitive context.

Too small: miss the sanitizer two frames up. Too large: expensive, attention dilutes. Calibrate against labeled data.

S06.4 — Autofix with Approval Gate

Confirmed finding
LLM generates minimal, targeted patch
Gate 1: linter clean
Gate 2: Semgrep re-scan clean (no NEW findings)
Gate 3: tests pass, coverage preserved
Gate 4: patch quality score above threshold
Open DRAFT PR
GATE 5: Human approval (non-negotiable)
Merge

Why approval is non-negotiable

LLM patches can introduce new vulnerabilities while fixing the reported one. Close an injection, miss a second one in the same function. Add an authz check after the sensitive op.

The PR is the approval mechanism. Draft PR, human merge, always. Auto-merging is an anti-pattern that will eventually ship a regression or a new CVE.

What you take into S07

The code review harness is operational: layered pipeline, FP triage, semantic memory, approval-gated autofix.

S07 shifts from code to architecture: threat modeling harnesses that ingest draw.io/Terraform/OpenAPI into DFDs and run STRIDE analysis.