Executable Hash and SBOM Provenance

Asqav binds the build-side provenance of the executing agent into the signed receipt via four optional wire fields: executable_hash, sbom_digest, slsa_provenance_pointer, and supply_chain_pointer. The 4-tuple binds "which build emitted this receipt" into the same tamper-evident envelope that already carries "what the agent did" and "what the policy decided".

What is the build-provenance 4-tuple?

Four OPTIONAL fields on POST /api/v1/agents/{id}/sign:

All four are OPTIONAL on the wire. None is mandatory on any receipt_type. The cloud accepts each independently. Producers populate whichever fields their build pipeline emits.

Why bind build provenance into the signed receipt?

A signed receipt without build provenance answers "did the agent perform action X under policy Y?". It does not answer "which build of the agent performed it?". When a CVE is later disclosed against a dependency, the second question is the one the auditor needs to triage scope. The 4-tuple keeps the two questions inside the same signed envelope, so the audit chain does not branch.

The same binding matters for the shadow-agent problem. Security teams keep reporting undeclared agents that run in production with no build record to correlate. A governed agent is the inverse: each signed action can carry a digest of the build that performed it. Pair this page with Shadow AI capture to put a signed receipt in front of LLM egress, or read The unsigned agent is the incident for the full pattern.

Industry attestation standards already cover the second question:

Asqav's 4-tuple references each of those artefacts by digest or URL. The signed receipt becomes the entry point an auditor uses to recover the SLSA envelope and the SBOM at audit time. The cryptographic binding guarantees the receipt was issued against THAT build, not a rebuild that papered over a known vulnerability.

How does this combine with the rest of the receipt?

The 4-tuple is orthogonal to every other wire field. A configuration-change receipt with full provenance binding looks like:

json
{
  "action_type": "mcp:config_update",
  "receipt_type": "protectmcp:lifecycle:configuration_change",
  "policy_decision": "none",
  "config_manifest_digest": "sha256:9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca7",
  "cve_inventory_digest": "sha256:1a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f7081",
  "executable_hash": "sha256:6f4b9c0c7a5d2e1f8b3a4c5d6e7f8090a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "sbom_digest": "sha256:2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f708192",
  "slsa_provenance_pointer": "https://attestations.example.com/slsa/build-abc123.intoto.jsonl",
  "supply_chain_pointer": "https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a"
}

The signed envelope binds every wire field. A verifier who later recovers the receipt cannot mutate any of the four pointers without breaking the ML-DSA signature.

Field constraints

A malformed value is rejected with HTTP 422 and a machine-readable error code:

The SDK enforces the same shapes client-side and raises before the HTTP roundtrip.

How do I produce a provenance-bound receipt?

Python SDK

python
import asqav

asqav.init()
agent = asqav.Agent.create("build-emitter")

sig = agent.sign(
    "build:provenance",
    {"image": "asqav/cloud:0.5.1"},
    compliance_mode=True,
    receipt_type="protectmcp:decision",
    executable_hash="sha256:<hex of executable>",
    sbom_digest="sha256:<hex of SBOM>",
    slsa_provenance_pointer="https://attestations.example.com/slsa/build-abc123.intoto.jsonl",
    supply_chain_pointer="https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a",
)

TypeScript SDK

typescript
import { Agent } from "@asqav/sdk";

const agent = Agent.attach({ /* ... */ });

await agent.sign({
  actionType: "build:provenance",
  context: { image: "asqav/cloud:0.5.1" },
  complianceMode: true,
  receiptType: "protectmcp:decision",
  executableHash: "sha256:<hex of executable>",
  sbomDigest: "sha256:<hex of SBOM>",
  slsaProvenancePointer: "https://attestations.example.com/slsa/build-abc123.intoto.jsonl",
  supplyChainPointer: "https://rekor.sigstore.dev/api/v1/log/entries/24296fb24b8ad77a",
});

curl

bash
curl -X POST https://api.asqav.com/api/v1/agents/agt_build_001/sign \
  -H "X-API-Key: $ASQAV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action_type": "build:provenance",
    "compliance_mode": true,
    "receipt_type": "protectmcp:decision",
    "executable_hash": "sha256:<hex>",
    "sbom_digest": "sha256:<hex>",
    "slsa_provenance_pointer": "https://attestations.example.com/slsa/build.intoto.jsonl",
    "supply_chain_pointer": "https://rekor.sigstore.dev/api/v1/log/entries/abc"
  }'

How does an auditor use the 4-tuple?

The auditor holds the receipt (with the 4-tuple) and the producer's archived build artefacts (kept by the producer's CI pipeline). To reconstruct the build identity, the auditor:

  1. Reads executable_hash and sbom_digest from the signed envelope.
  2. Pulls the matching executable + SBOM document from the producer's artefact archive.
  3. Rehashes each and confirms the values match the receipt's digests byte-for-byte.
  4. Follows slsa_provenance_pointer to the SLSA attestation envelope and verifies the in-toto layout.
  5. Follows supply_chain_pointer to the Sigstore Rekor entry and verifies inclusion in the transparency log.

Each step is independently verifiable. A mismatch on any step is a tamper signal. Matching values across all four steps prove the receipt was emitted against the exact build artefact the producer claims.

How does this relate to third-party signed-build provenance vendors?

Standalone provenance-attestation vendors emit a separate signed envelope that an auditor must correlate with the action log. Asqav publishes the same evidence as part of the action log itself. The auditor needs one canonical chain, not two.

This subsumption is documented in the IETF Compliance Receipts draft under the optional-extensions section, alongside config_manifest_digest, cve_inventory_digest, and tool_fingerprint. Producers MAY emit a separate SLSA or Sigstore attestation in parallel. The receipt's slsa_provenance_pointer and supply_chain_pointer then resolve to those artefacts directly.

Related documentation