findings[] entry in scan.json is a one-attack record with
enough context to replay the attack, audit the verdict, and route to a
fix. Source of truth:
models/finding.py
- the per-finding emission in
reports/json_report.py.
When to use this page
- You opened a finding in
scan.jsonand want to know what every field means before you triage it. - You’re writing a parser that walks
scan.jsonand needs to know which fields are guaranteed present vs nullable. - You want to replay a finding deterministically (the PoV gate output
trigger_prompt).
The finding shape
Identity
A single probe can produce multiple findings on one scan (one per
landed turn).
probe_id is your group-by key.
Mapping (the OWASP / MITRE / CSA triple)
Every finding carries the same triple, inherited from the probe YAML. The triple-framework gate inmodels/probe.py:_coerce_probe
enforces that all three are populated before a probe loads.
The triple is the same triple every emitter carries — SARIF
rules[].properties.asi / properties.mitre_atlas /
properties.csa, JUnit <system-out> tags, Markdown’s per-finding
header. Cross-emitter consistency is asserted by the canonical
schema.
Verdict
success=true is what the AIVSS penalty counts (and what the
high-severity band cap fires on). A finding emitted with
success=false is recorded for trend tracking but does not penalise
the score.
Evidence + replay
The replay contract
trigger_prompt is deliberately sufficient to replay the attack
against the same target — no hidden state, no extra config. The PoV
runner does exactly that: rerun trigger_prompt N times under the
same target adapter and report the success rate.
--pov-gate) runs this automatically before scoring and
drops findings whose reliability falls below the gate threshold so the
score never reflects a one-in-twenty flake.
Redaction (always on)
PII and credential redaction is on by default for every emitter. The sharedredact_finding
helper scrubs five fields before serialisation:
summarydescription(probe-level; carried into the SARIF rule)trigger_prompttranscript_ref(the path string, in case it embeds an identifier)evidencepayload bytes (the contents oftranscript_ref)
password= assignments. Install
agent-guardian[full] to layer presidio on top for richer PII (names,
phone numbers, emails).
This isn’t a knob — a security scanner must never re-emit a captured
secret.
What the bundle directory looks like
--bundle ./out/ emits a checksummed tree alongside the JSON report:
manifest.json carries SHA-256 + byte count for every file plus
the scan envelope (id, AIVSS, band, formula version). This is the
artifact you archive for audit — see
reports/bundle.py.
Walking findings in code
The minimal idiom — group by ASI category, surface the critical-band findings first:Next step
AIVSS score
The five-step pipeline + the
mode_authoritative rule that gates
--fail-under.Severity levels
The four severity tiers + how each contributes to the headline.
Report schema
Field-by-field reference for
agentguardian-scan-v1.JSON export
Sample
scan.json end-to-end + the canonical-form rules.