Report Format
One canonical report-v1 document renders to Markdown, redacted JSON, SARIF 2.1.0, and escaped standalone HTML. Redaction and escaping are part of the renderer, not an afterthought.
One canonical source
A run produces exactly one canonical JSON document. Markdown, redacted JSON, SARIF 2.1.0, and escaped standalone HTML are all derived from it. There is no separate authoring path for the human-readable version, which is what stops the prose and the data from disagreeing.
The renderer is deliberately dependency-free. It validates the minimum report-v1 envelope, recursively redacts secret-bearing values, and treats all report text as untrusted when producing Markdown and HTML.
The report envelope
| Field | Contents |
|---|---|
scope_id | The scope record this run was authorized under. |
mode | STATIC, LOCAL, STAGING, or PRODUCTION_SAFE. |
coverage | APPLICABLE, NOT_APPLICABLE, UNKNOWN, BLOCKED, TOTAL, and integrity_critical_unknown. |
tools | Which scanners and harnesses contributed evidence. |
evidence | The evidence records findings cite. |
findings | Verified and candidate findings with their evidence chains. |
rejected_false_positives | Candidates the verifier refuted, with reasons. |
blocked_checks | Checks that could not be decided, and why. |
release_recommendation | The run recommendation — advisory only; the gate recomputes it. |
redaction_summary | What the renderer removed. |
All of those are required by schemas/report-v1.schema.json. A report missing rejected_false_positives or blocked_checks does not validate.
What a finding carries
The report guidance lists the fields each finding should contain:
- ID and title.
- Severity and confidence, as separate values.
- Affected surface.
- CWE and OWASP mapping where useful.
- Prerequisites.
- The evidence chain.
- Safe reproduction.
- Impact.
- Root cause.
- Fix.
- Regression proof.
- Residual risk.
The renderer knows the seven evidence-chain links by name — attacker control, reachability, boundary failure, safe reproduction, impact, preconditions, root cause — and renders them as a labelled chain rather than as free prose.
Rendering
python -m reports.report_renderer examples/report.example.json --format markdown
python -m reports.report_renderer report.canonical.json --format json --output report.json
python -m reports.report_renderer report.canonical.json --format sarif --output report.sarif
python -m reports.report_renderer report.canonical.json --format html --output report.htmlpython scripts/security_gate.py examples/report.example.json --policy policies/default.json- Markdown
- For pull requests, tickets, and review threads.
- Redacted JSON
- For storage and for downstream policy tooling.
- SARIF 2.1.0
- For code-scanning surfaces that already consume SARIF.
- Standalone HTML
- Escaped and self-contained, for sharing outside a code host.
Redaction and escaping
- Secret-bearing keys are matched by name: api key, authorization, cookie, credential, mnemonic, password, private key, seed phrase, secret, token.
- Secret-shaped values are matched by pattern, including PEM private key blocks, bearer tokens, AWS access key IDs, GitHub tokens, and OpenAI-style keys.
- Redaction is recursive over the whole document, not applied only to a known list of fields.
- What was removed is recorded in redaction_summary rather than silently dropped.