Skip to main content
RunBook Academy

Git, CI/CD & GitOpsLXX · ProvenanceEnvelopes

in-toto attestations — the standard format and predicate types

Advanced⏱ ~22 mingit

What you'll learn

  • Describe the in-toto Statement structure: subject, predicateType, predicate
  • Distinguish the in-toto Statement from the DSSE envelope that signs it
  • Identify the predicate types used by SLSA, SPDX, CycloneDX, VEX, and Link
  • Read an in-toto attestation and verify the predicate type matches the consumer expectation

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

in-toto is the envelope format for the supply-chain claims this course generates. The envelope is a JSON document with two layers: the Statement (the typed claim about a subject) and the DSSE envelope (the signed bytes over the Statement). The predicate type is the field that names what the claim is; the predicate is the payload of the claim. The format is the same shape whether the claim is a SLSA provenance, an SPDX SBOM, a CycloneDX SBOM, a VEX, or a custom Link; the predicate type is the only thing that changes.

The Statement

The Statement is the unsigned claim with three top-level fields: predicateType (the URI that names what the claim is), subject (the array of name+digest pairs that identifies the artifact), and predicate (the payload whose shape follows the predicateType). The _type field identifies the envelope version. The verifier dispatches on predicateType; a provenance verifier expects https://slsa.dev/provenance/v1, an SBOM verifier expects https://spdx.dev/Document or https://cyclonedx.org/bom, a VEX verifier expects https://openvex.dev/ns/v0.2.0. The verifier rejects any attestation whose predicateType does not match the expected type.

The DSSE envelope

The Statement is wrapped in a DSSE envelope before it is signed. The envelope has three fields: payloadType (the serialization of the payload, always application/vnd.in-toto+json), payload (the base64-encoded Statement), and signatures (an array of signature objects, each bound to a keyid the verifier can identify).

flowchart LR
    A["Statement"] --> B["payload"]
    B --> C["DSSE envelope"]
    C --> D["Signature"]
    D --> E["OCI referrer"]
    E --> F["Registry"]
    F --> G["Verifier"]
    G --> H["predicateType match"]
    G --> I["Signature valid"]
    G --> J["Subject matches"]
    G --> K["Admit"]
    G --> L["Deny"]

The verifier fetches the referrer, decodes the payload, checks the predicateType matches the expected type, verifies the signature, checks the subject matches the artifact, and admits or denies.

The predicate types

The in-toto project assigns URI-shaped predicate types to the common claims:

  • https://slsa.dev/provenance/v1 — SLSA build provenance. The predicate carries buildDefinition, runDetails, and metadata. The verifier expects this type when the claim is “where did this artifact come from?”.
  • https://spdx.dev/Document — SPDX SBOM. The verifier expects this when the claim is “what is in this artifact, in SPDX format?”.
  • https://cyclonedx.org/bom — CycloneDX SBOM. The verifier expects this when the claim is “what is in this artifact, in CycloneDX format?”.
  • https://openvex.dev/ns/v0.2.0 — OpenVEX. The predicate enumerates the vulnerabilities that are not affecting the artifact.
  • https://in-toto.io/Link/v0.3 — in-toto Link. Records handoffs between build steps.

The same envelope shape carries all of these claims. Adding a new claim type means choosing a new URI; the envelope does not change.

Production discipline

  1. Generate the attestation with the correct predicate type. A provenance attestation must have https://slsa.dev/provenance/v1; an SBOM must have https://spdx.dev/Document or https://cyclonedx.org/bom. The verifier dispatches on this.
  2. Verify the predicate type in the consumer. The verifier must check the predicateType matches the expected type before trusting the predicate.
  3. Use the same envelope shape for every claim. The Statement and DSSE envelope are the standard; the predicate type is the only thing that changes.
  4. Document the predicate types your consumers expect. The URI is the contract; the contract is the documentation.

Cross-course references

  • Git, CI/CD & GitOps — Part LXX-01 (What Provenance Is) is the provenance concept; LXX-03 is the envelope format.
  • Git, CI/CD & GitOps — Part LXVIII-04 (SBOM Distribution and Attestation) is the SBOM that uses the same envelope.
  • Container Security for Production Sysadmins — Part VIII (VEX and Vulnerability Operations) is the VEX claim in the same envelope.

Quiz

Knowledge check · 4 questions

  1. Q1. Which field of an in-toto Statement identifies the artifact the claim is about?

  2. Q2. The in-toto Statement and the DSSE envelope are the same document with different names.

  3. Q3. Name the three top-level fields of an in-toto Statement and what each one identifies.

  4. Q4. Diagnose why the verifier is rejecting every attestation as a malformed provenance and recommend the fix.

    Team T's CI generates an SBOM, wraps it in an in-toto attestation, and uploads it to the registry next to the image. The provenance verifier in the admission controller rejects every attestation with the message 'unexpected predicateType, expected slsa.dev/provenance/v1'. The SBOM is clearly signed and the signature is valid.

Passing score: 75%. Answers are checked in this browser.