agentguardian-scan-v1) and SARIF 2.1.0 for code-scanning tool consumers. Both are deterministic (sorted-key), both are PII-redacted by default, and both surface the same underlying Scan model.
When to use this
- You are writing a parser, dashboard, or gate against a report and need to know the exact field set.
- You are debugging why a downstream consumer (GHAS, Sonar) rejected a SARIF file.
- You need to know which fields are signed and which are advisory metadata.
docs/_assets/sample-report.pdf. Open it to see the field set before you run your first scan.
Produce a report
JSON schema: agentguardian-scan-v1
Top-level keys in canonical (sorted) order:
| Field | Type | Notes |
|---|---|---|
aivss | int 0-100 | Final AIVSS score. |
aivss_formula_version | str | Version of the AIVSS formula that produced aivss. |
asi_scores | {str: float} | Per-ASI-category sub-scores (ASI01..ASI10). |
band | str | One of EXCELLENT, GOOD, WARNING, POOR, CRITICAL, not_evaluated. |
budget | object | null | {cap_usd, spent_usd, pct_of_cap, soft_stop_fraction, finalise_truncated}. |
completeness | object | null | {agents_planned, agents_completed, agents_cut_short, turns_used, turns_planned, pct}. |
cost_usd | float | Actual spend across all LLM roles. |
coverage | object | Counters reconstructed from on-disk memory.jsonl. |
coverage_grade | str | A..F. A = every ASI category covered by real evidence. |
created_at | str (ISO 8601) | UTC if no tzinfo, else local-with-offset. |
duration_seconds | float | Wall-clock runtime. |
engine | {commander, attacker, evaluator} | Model IDs (e.g. openai:gpt-4o, stub). |
evaluation_mode | str | real | stub | mixed. A stub evaluator yields a non-authoritative score. |
findings | [Finding] | See below. |
findings_summary | {critical, high, medium, low} | Counts per severity. |
mode | str | fast | smart | full. |
mode_authoritative | bool | False for non-FULL modes — --fail-under must refuse to gate-pass. |
package_version | str | The agent-guardian version that produced the scan. |
probe_library_version | str | Probe corpus version. |
scan_id | str | Stable scan identifier. |
schema | str | Always agentguardian-scan-v1. |
scoring_valid | bool | False if the AIVSS number is not authoritative. |
signatures | object | {hmac_sha256, ed25519}. Only present when sign=True (the CLI default). |
stopped_reason | str | completed | budget | early_stop | cancelled. |
sub_scores | {str: float} | Raw component scores used to derive aivss. |
target | {mode, ref, inferred_goal, profile_source} | What was scanned. |
tier | str | T1..T4. |
tokens_total | int | Combined input + output tokens. |
undertested | [str] | ASI categories exercised too thinly to claim safety. |
audit | object | Optional — present when a Stage 1B contract authorised the scan. |
Finding object
Every entry infindings[] carries the full attack record:
| Field | Type | Notes |
|---|---|---|
id | str | Stable finding ID. |
probe_id | str | The probe that triggered. |
asi | str | One of ASI01..ASI10. |
mitre_atlas | [str] | ATLAS technique IDs (AML.TNNNN[.NNN]) or named v5.4.0 techniques. |
csa_category | str | One of the twelve CSA Agentic-RT categories (kebab-case). |
severity | str | critical | high | medium | low. |
attempt_count | int | How many turns the attacker spent on this scenario. |
success | bool | Whether the attack succeeded. |
confidence | float 0-1 | Evaluator confidence in the verdict. |
summary | str | One-line description (redacted). |
transcript_ref | str | null | Path under ~/.agentguardian/scans/<id>/. |
trigger_prompt | str | null | The attack prompt (redacted). Drives PoV replay. |
pov_reference | str | null | Relative path to the PoV reproducer (e.g. pov/<id>.py). |
pov_reliability | float | null | Wilson-lower-bound N-fold rerun success rate. |
created_at | str (ISO 8601) | When the finding was recorded. |
Sample JSON (header)
Signing model
Whensign=True (CLI default), signatures.hmac_sha256 and signatures.ed25519 are computed over the canonical JSON of the payload with the signatures key removed. This makes signing idempotent: re-signing an already-signed payload reproduces the same bytes. Verifiers reconstruct the signed input the same way.
To verify a report:
verify exits non-zero and prints UNANCHORED. Details in Signatures.
SARIF 2.1.0 schema
The SARIF emitter wraps a singlerun per scan: one rule per observed probe_id, one result per finding. The bundled SARIF 2.1.0 schema is enforced before the file is written — a malformed payload raises ReportError rather than persisting a file that downstream consumers would silently reject.
Top-level shape
Severity mapping
The AgentGuardian severity is mapped to SARIF’slevel field as follows:
| AgentGuardian severity | SARIF level |
|---|---|
critical | error |
high | error |
medium | warning |
low | note |
warning.
Result properties
Eachresult carries the verdict plus the metadata SARIF has no native slot for:
properties key | Source |
|---|---|
aivss_severity | finding.severity.value |
asi | finding.asi.value |
mitre_atlas | finding.mitre_atlas |
csa | finding.csa_category.value |
confidence | finding.confidence |
success | finding.success |
attempt_count | finding.attempt_count |
finding_id | finding.id |
pov_reference | finding.pov_reference (omitted when null) |
pov_reliability | finding.pov_reliability (omitted when null) |
Rule properties
Each rule (one perprobe_id observed) carries ASI / CSA / MITRE metadata so downstream consumers don’t lose taxonomy when SARIF is the only artifact they ingest:
Contract provenance (Stage 1B)
When a scan was authorised by a Rules-of-Engagement contract, four provenance keys are lifted ontoruns[0].properties:
contract_sha256contract_versionauthorization_refenvironment
runs[0].invocations[0].properties:
budgets_grantedbudgets_consumedsuppressed_tool_attemptsstarted_at
run.invocations is always an array (SARIF 2.1.0 rejects a singular invocation key).
How JSON, SARIF, and bundles fit together
Schema versioning
| Surface | Version field | Current |
|---|---|---|
| JSON | schema | agentguardian-scan-v1 |
| JSON | aivss_formula_version | bumped when scoring weights change |
| JSON | probe_library_version | bumped when the probe corpus changes |
| SARIF | version | 2.1.0 (fixed) |
| SARIF | $schema | https://json.schemastore.org/sarif-2.1.0.json |
schema string. Additive fields do not.
Next step
- Wire SARIF into GitHub code-scanning in GitHub Actions.
- Package the JSON, SARIF, PoVs, and transcripts together with Evidence packs.
- Verify provenance end-to-end in Signatures.