Safeguard
Concepts

What is a Software Attestation

A software attestation is a signed, machine-readable claim about an artifact — who built it, what it contains, which checks it passed — that a machine can verify before trusting it.

Aisha Bello
Application Security Engineer
6 min read

A software attestation is a cryptographically signed, machine-readable statement in which an identified party makes a specific claim about a specific artifact — identified by its content digest — such as "I built this from commit abc1234," "this contains these components," or "this passed our vulnerability scan on this date." The format that won is in-toto: a JSON statement binding a subject (name plus sha256) to a predicate (the claim), wrapped in a DSSE signing envelope. If you remember one thing, make it this: an attestation is a signature over a claim about bytes, not over the bytes themselves.

That distinction is what makes attestations composable. One artifact can carry five attestations from five different parties — builder, scanner, reviewer, license auditor, release manager — each independently verifiable, each falsifiable in isolation.

The anatomy, concretely

Every in-toto attestation has three layers:

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    { "name": "api-server", "digest": { "sha256": "8f43e1..." } }
  ],
  "predicateType": "https://slsa.dev/provenance/v1",
  "predicate": { }
}
  • Subject: the artifact(s) the claim is about, always by digest. Rename the file, the attestation still applies; change one byte, it no longer does.
  • Predicate type: a URI declaring what kind of claim follows, so verifiers can parse it. Common ones: SLSA provenance, SPDX or CycloneDX (SBOM-as-attestation), and vulnerability scan results.
  • Predicate: the claim body itself.

The signed wrapper is DSSE (Dead Simple Signing Envelope), which signs the payload together with its type to prevent confusion attacks. In the Sigstore flow, the signature comes from a short-lived certificate tied to an OIDC identity — a GitHub Actions workflow, a Google service account — and gets logged to the Rekor transparency log. No long-lived private keys to rotate, leak, or lose.

Attestation types you'll actually encounter

Predicate typeClaimTypical producer
SLSA provenance"Built from repo X at commit Y by builder Z"CI platform (GitHub Actions, Tekton Chains)
SPDX / CycloneDX"These are the components inside"SBOM generator (Syft, cdxgen)
Vulnerability scan"Scanned with tool T at time N, results R"Trivy, Grype, commercial scanners
Test/verification results"Suite S passed on this artifact"CI test stage
in-toto layout/link"Step k of the defined pipeline ran as declared"in-toto framework itself

Provenance is the flagship — it's the attestation that addresses build tampering, and we compare the competing predicate schemas in our in-toto attestation formats review. But the pattern generalizes: anything you currently assert in a spreadsheet or a compliance PDF ("we scan every release") can become a signed statement attached to the artifact it describes.

Producing and verifying, with real commands

For a container image, cosign is the workhorse:

# Attach an SBOM as a signed attestation (keyless)
syft acme/api:1.4 -o cyclonedx-json > sbom.json
cosign attest --type cyclonedx --predicate sbom.json acme/api:1.4

# Attach a vulnerability scan result
trivy image --format cosign-vuln acme/api:1.4 > scan.json
cosign attest --type vuln --predicate scan.json acme/api:1.4

# Verify: correct identity AND correct claim type
cosign verify-attestation acme/api:1.4 \
  --type cyclonedx \
  --certificate-identity-regexp 'https://github.com/acme/api/\.github/workflows/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

The verification flags deserve attention because this is where people create decorative security. cosign verify-attestation without --certificate-identity checks only that someone with some Sigstore identity signed something — an attacker's fork signing its own attestation passes. Pin the identity to your repo and workflow, pin the issuer, and check the predicate type. Then feed the predicate into a policy engine (the cosign CUE/Rego options, or Kyverno's verifyImages rules) to enforce claims like "no critical findings in the attached scan" at admission time.

Why bother: the trust argument

Every deployment pipeline already embodies trust decisions — they're just implicit. "We deploy what CI produced" assumes CI wasn't tampered with. "We scanned it" assumes the scan ran against the same bytes that shipped. Attestations make each assumption explicit, signed, and checkable at the moment of consumption rather than reconstructed during the post-incident timeline meeting.

The compliance angle is real too, if less glamorous. SLSA levels, NIST SSDF (SP 800-218), and the US government's self-attestation form for software suppliers all reduce to structured claims about build practices — much easier to substantiate when the claims exist as signed documents per release instead of prose in a policy wiki. Supply chain platforms are converging on this model; Safeguard verifies attestations on ingested artifacts and flags releases that are missing the ones your policy requires, and its SBOM Studio emits component inventories in attestation form so downstream verifiers get signatures, not just JSON.

A dry observation from the trenches: teams generate attestations months before anything verifies them. That's fine — coverage first, enforcement second — but put a verification date on the roadmap, or you've built a very cryptographically sophisticated logging system.

Frequently asked questions

How is an attestation different from just signing the artifact?

A plain signature says "key X endorsed these bytes" and nothing else — no who, what stage, what claim. An attestation carries a structured claim with a declared type, so verifiers can enforce policy on the content ("built by our CI from our repo") rather than merely on key possession. Signatures authenticate; attestations explain and authenticate.

Where are attestations stored?

For containers, in the OCI registry alongside the image (cosign stores them as OCI artifacts referencing the image digest). For other artifacts: package registries (npm stores provenance next to the tarball) or any blob store, since the attestation is self-contained and bound to the digest. The Rekor transparency log additionally records signing events publicly.

Can an attestation be revoked?

Not directly — a signed statement can't be unsigned. In practice you handle it at the policy layer: verifiers can distrust an identity from a given time window (certificate compromise), or a newer attestation can supersede an older one, as VEX documents do with status updates. Transparency logs make silent rewriting detectable.

Do small teams need this or is it enterprise ceremony?

The hosted-CI path (npm publish --provenance, cosign keyless signing, the SLSA GitHub generator workflows) costs an afternoon and no key infrastructure, which has moved baseline attestation from "enterprise ceremony" to "cheap default." Enforcement policies can come later; producing the evidence from day one is close to free.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.