Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions conformance/examples/scan-attestation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Scan attestation vs compliance attestation

A worked example for the two attestation classes described in `spec/ard.md`
§5.2. The entry carries one of each, on purpose: the difference is only visible
when they sit side by side.

## Files

| File | What it is |
| :--- | :--- |
| `ai-catalog.json` | The catalog. One entry, two attestations. |
| `invoice-reader.scan.sarif` | The scan attestation document the entry references. |

The scanned artifact itself is not vendored here — in a real deployment it is
served by the publisher at the entry's `url`, and the attestation refers to it
by digest rather than by copy.

## What each attestation claims

`SOC2-Type2` is a **compliance attestation**. It says the publisher operates an
audited control environment. It says nothing about the invoice reader itself —
the same certificate would appear unchanged on every entry this publisher lists,
including one shipped yesterday and never reviewed.

The scan attestation says the artifact at the entry's `url` was analysed for
tool-poisoning and hidden-capability content. What makes that claim checkable is
not the entry — it is the referenced document.

## Following the binding

The entry's `digest` covers the **attestation document**, per the `digest`
description in `spec/schemas/ai-catalog.schema.json`:

```sh
shasum -a 256 invoice-reader.scan.sarif
# cdbd706458d30031292cb80c697357257e2fcb739917dc68d67c7b8925d3bee3
```

That hash is real and recomputable from the file here.

The binding to the **scanned artifact** lives one level further in, inside that
document, in SARIF's `runs[].artifacts[].hashes`. That value is illustrative,
since the artifact is served by the publisher rather than vendored here — but it
is the load-bearing one: change the artifact and it stops matching, so the scan
result cannot follow an artifact it was not computed over. The SOC 2 attestation
carries no digest because its report is not materialised here; `digest` is
optional.

The document also names what the scan was run under — `tool.driver.name` and
`version`, the `rules[]` it evaluated, and a ruleset name and version — so a
consumer can judge coverage instead of treating the attestation's presence as a
verdict. ARD does not require SARIF; any format that names its standard and
ruleset satisfies the SHOULD in §5.2.

## What this example does not claim

- **The type token is illustrative.** ARD does not define or register
attestation type names, and `agent-threat-scan` here is a value chosen by a
fictional publisher, not spec vocabulary.
- **A scan attestation is not a guarantee.** It is bounded by the ruleset named
in it. A finding-free scan under one ruleset is not a finding-free scan under
another, and neither is a statement about behaviour at runtime.
- **The digest binds content, not honesty.** It proves the analysed bytes are
the bytes served. It does not prove the publisher was truthful about which
scanner ran — that is what verifying the trust manifest's signature is for.

## Validate

```sh
cd conformance
./bin/conformance-test manifest examples/scan-attestation/ai-catalog.json
```
37 changes: 37 additions & 0 deletions conformance/examples/scan-attestation/ai-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"specVersion": "1.0",
"host": {
"displayName": "Example Tool Publisher",
"identifier": "did:web:tools.example.com"
},
"entries": [
{
"identifier": "urn:air:tools.example.com:server:invoice-reader",
"displayName": "Invoice Reader",
"type": "application/mcp-server-card+json",
"url": "https://tools.example.com/mcp/invoice-reader.json",
"description": "Reads uploaded invoices and returns structured line items.",
"representativeQueries": [
"extract the line items from this invoice",
"what is the total on the attached invoice"
],
"trustManifest": {
"identity": "spiffe://tools.example.com/mcp/invoice-reader",
"identityType": "spiffe",
"attestations": [
{
"type": "SOC2-Type2",
"uri": "https://tools.example.com/trust/soc2-2026.pdf",
"mediaType": "application/pdf"
},
{
"type": "agent-threat-scan",
"uri": "https://tools.example.com/trust/invoice-reader.scan.sarif",
"mediaType": "application/sarif+json",
"digest": "sha256:cdbd706458d30031292cb80c697357257e2fcb739917dc68d67c7b8925d3bee3"
}
]
}
}
]
}
51 changes: 51 additions & 0 deletions conformance/examples/scan-attestation/invoice-reader.scan.sarif
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "example-agent-scanner",
"version": "2.3.0",
"informationUri": "https://scanner.example.com/",
"rules": [
{
"id": "EX-TOOL-POISONING-001",
"name": "ToolDescriptionInstructionInjection",
"shortDescription": {
"text": "Tool description contains instructions directed at the model."
}
},
{
"id": "EX-HIDDEN-CAPABILITY-002",
"name": "UndeclaredNetworkEgress",
"shortDescription": {
"text": "Tool performs network egress not declared in its schema."
}
}
]
}
},
"artifacts": [
{
"location": {
"uri": "invoice-reader.json"
},
"hashes": {
"sha-256": "d27f6473cd6b4a8ec3623a9ec01e8b42d0c607b0bc416237720f20a28f114a5b"
}
}
],
"results": [],
"invocations": [
{
"executionSuccessful": true,
"properties": {
"rulesetName": "example-agent-ruleset",
"rulesetVersion": "2026.08"
}
}
]
}
]
}
10 changes: 10 additions & 0 deletions spec/ard.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,18 @@ Provides verifiable proof of a claim (e.g., compliance certifications).
| :---- | :---- | :---- |
| type | String | **Required**. Attestation type (e.g., "SOC2-Type2", "HIPAA-Audit"). |
| uri | String | **Required**. Location of the attestation document. |
| mediaType | String | **Required**. Format of the attestation document (e.g., "application/pdf", "application/sarif+json"). |
| digest | String | Optional. Cryptographic hash for integrity verification. |

Attestation `type` values fall into two semantically distinct classes:

* **Compliance attestations** (e.g., `SOC2-Type2`, `HIPAA-Audit`) attest to an organizational process or control environment. They are a statement about the publisher, not about the specific artifact in the entry.
* **Scan attestations** attest to the result of an automated security analysis of the artifact's own content — for example, screening a tool or agent manifest for tool-poisoning, hidden-capability, or prompt-injection patterns. Unlike a compliance attestation, a scan attestation is a claim about this artifact, bounded by the scanning standard and ruleset it was produced under. This specification names the class; it does not define or register type names for it.

A registry or orchestrator MUST NOT present a compliance attestation, or a `filter` match on one (§7.1), as a safety or security assessment of the artifact in the entry. This is the counterpart, at the trust layer, to the relevance-scoring caveats in §7.2 and §7.3: just as a relevance score MUST NOT be read as a safety judgment, neither may a compliance attestation. A scan attestation is the form of this object that carries an artifact-scoped safety claim.

A publisher that lists a scan attestation SHOULD ensure the referenced document names the standard and ruleset the scan was produced under, so a consumer can interpret the coverage and limits of the claim. That document SHOULD itself identify the scanned subject by cryptographic digest — as in-toto statements and SARIF `artifacts[].hashes` both do — so the claim cannot be silently reattached to an artifact it was not computed over. Note that the `digest` member above covers the attestation document, not the artifact.

### 5.3 Provenance Link Object

Records lineage and source information.
Expand Down