Evidence Adapters
Nine adapters normalize Semgrep, CodeQL, SARIF, OSV, Gitleaks, Trivy, package audits, Playwright, ZAP, and Nuclei reports into one evidence envelope. They do not run scans.
What an adapter does
The adapters are standard-library only. Every emitted record has status: CANDIDATE, with assessment, severity, and verification all set to UNASSESSED. The original tool severity and confidence survive only inside tool_signal, marked trusted_for_assessment: false.
That single flag is the whole design. A tool can tell you where to look. It cannot tell you what is true, and the data model refuses to let it try.
The nine adapters
Nine adapter modules cover eleven CLI names, because SARIF is shared between the generic SARIF path and the CodeQL path, and package audit handles both npm and pnpm.
| Adapter | Input | Evidence lane |
|---|---|---|
| Semgrep | Semgrep JSON report | Static analysis — dangerous sinks and candidate flows |
| CodeQL | CodeQL SARIF report | Static analysis — dataflow queries |
| SARIF | Any SARIF 2.1.0 producer | Static analysis — generic tool intake |
| OSV | OSV-Scanner JSON | Dependency and supply chain |
| Gitleaks | Gitleaks JSON | Secret exposure — values omitted |
| Trivy | Trivy JSON | Dependency, image, and secret scanning — secret values omitted |
| Package audit | npm audit and pnpm audit JSON | Dependency advisories |
| Playwright | Playwright JSON results | Browser and runtime evidence |
| ZAP | ZAP JSON report | Passive DAST signals |
| Nuclei | Nuclei JSONL | Template matches — results and bodies omitted |
Custom organization scanners and test harnesses can join through the same envelope; the adapter is not the authority in any of these cases.
Normalizing a report
python -m adapters.cli semgrep semgrep.json --pretty
python -m adapters.cli codeql codeql.sarif -o normalized.json
python -m adapters.cli sarif report.sarif
python -m adapters.cli osv osv.json
python -m adapters.cli trivy trivy.json
python -m adapters.cli gitleaks gitleaks.json
python -m adapters.cli npm-audit npm-audit.json
python -m adapters.cli pnpm-audit pnpm-audit.json
python -m adapters.cli playwright playwright.json
python -m adapters.cli zap zap.json
python -m adapters.cli nuclei nuclei.jsonlpython -m adapters.cli --helppython -m unittest discover -s adapters/tests -vRedaction
- The Trivy and Gitleaks secret paths omit captured values. A secret finding tells you a secret was found, not what it was.
- The Nuclei adapter omits extracted results and request and response bodies.
- Original tool reports keep their own data classification. Normalizing does not declassify them.
- The report renderer applies a second redaction pass over the canonical document before rendering.
Bounded dynamic commands
adapters/safety.py constructs commands but never executes them. The construction itself is constrained by the execution mode.
- Local context
- Accepts loopback HTTP and HTTPS targets only.
- Staging context
- Additionally requires an exact hostname allowlist.
- Production and uncontrolled
- Fail closed.
- ZAP
- Emits only a baseline passive command.
- Nuclei
- Requires explicit, existing YAML template files on an operator-supplied allowlist, applies low concurrency and rate defaults, and rejects remote, directory-wide, DAST, fuzz, headless, and code-protocol template profiles.
Checked-in profiles live in adapters/profiles/. They are constraints, not authorization.
Evidence lanes
Tools are evidence producers. The guidance separates what each lane is good for, and what it cannot conclude.
- Static analysis enumerates dangerous sinks, traces candidate flows, detects repeated insecure patterns, and supports variant analysis after a verified root cause. It does not establish reachability on its own.
- Dependency analysis must separate three distinct facts: a vulnerable dependency is present, a vulnerable code path is reachable, and the exploit preconditions are satisfied.
- Browser and runtime verification proves what static tooling cannot see: bundle boundaries, cookie and origin behaviour, CSP and DOM behaviour, direct-URL authorization, and race-sensitive transitions.
- API testing prefers schema-aware bounded requests against local or staging fixtures, comparing role, object, and action differences across alternate endpoints, bulk routes, pagination, search, export, and error paths.
- DAST and template tools produce hypotheses. They are not a licence for indiscriminate scanning or rate-limit evasion.