Artifact Attestations, SBOMs, Build Provenance, Verification, and SLSA-Oriented Workflows: Configuration, Design Choices, and Tradeoffs
Provenance becomes useful only when a team decides what to attest, which predicates are required, where verification must run, and which repository/workflow/ref/runner identities are acceptable. This lesson compares binaries, packages and container images; provenance versus SBOM evidence; publish-time versus consumer-time checks; and GitHub-specific claims versus the broader SLSA model.
Learning objectives
- Choose between attesting a file/binary and attesting an OCI/container/package subject by immutable digest.
- Decide when build provenance alone is sufficient and when an SBOM or additional predicate is part of acceptance policy.
- Place verification at publish, promotion, deployment and consumer boundaries according to who controls each trust transition.
- Design repository/workflow/ref/issuer/runner constraints that are narrow enough to prevent substitution but maintainable enough to operate.
- Separate GitHub’s product-specific SLSA guidance from a full claim evaluated against the current SLSA specification.
1. What should be the attestation subject?
Attest the thing a consumer actually receives and makes a trust decision about. If users download a tarball, the tarball digest should be the subject. If a deployment pulls an OCI image, the image digest should be the subject. Signing source files one by one is usually weaker operationally because the deployed package can still differ from those source inputs.
| Distribution object | Recommended subject identity | Why |
|---|---|---|
| Binary/archive | File SHA-256 via subject-path |
Verifier can hash the downloaded bytes directly. |
| OCI/container image |
Fully qualified image name + immutable
sha256: digest
|
Registry tag may move; digest identifies manifest/content. |
| Package ecosystem artifact | Exact package file/version digest where supported by distribution flow | Consumers need evidence tied to installed/distributed bytes. |
| Manifest of many artifacts | Manifest file digest, plus listed child digests | Scales verification when the manifest itself is governed. |
2. Provenance-only versus provenance + SBOM
Build provenance is the minimum evidence when the policy question is builder identity and source/build context. Add an SBOM when consumers must reason about dependencies, licenses, incident impact or component policy. Adding more predicates is not automatically better: each predicate needs a producer, schema, lifecycle and verification rule.
| Policy need | Evidence choice | Caveat |
|---|---|---|
| Verify expected GitHub workflow built exact bytes | SLSA provenance attestation | Still inspect source/build policy; provenance is not vulnerability scanning. |
| Respond to vulnerable component advisory | SBOM + provenance | SBOM completeness/accuracy determines usefulness. |
| Runtime deployment admission | Provenance, and SBOM if component policy is enforced | Verification must run before execution, not after. |
| Audit reproducibility | Provenance + retained source/build inputs; optionally reproducible-build comparison | Attestation alone does not make a build reproducible. |
3. Verify at publish time, consumer time, or both?
Producer-side verification catches pipeline mistakes early: wrong subject path, missing attestation, or malformed SBOM. Consumer-side verification is the security boundary that detects substitution after publication. A producer cannot safely replace the consumer’s check because the distribution channel itself may be the thing under attack.
| Boundary | What verification catches | Recommended stance |
|---|---|---|
| Immediately after build | Attestation generation mistakes and wrong subject selection | Useful self-test, not sufficient alone. |
| Release/package publication | Mismatch between build output and published object | Require before marking a release/promoting a package when possible. |
| Environment promotion | Wrong bytes/tag selected for staging/production | Verify exact immutable subject again. |
| External consumer/deployment | Distribution substitution and untrusted builder identity | Highest-value independent check. |
4. Trust policy: repository, workflow, ref, issuer and runner
The strongest policy is not “signature valid.” It states which
authenticated identity is allowed to sign this kind of artifact.
Current gh attestation verify lets you constrain
repository/owner, signer workflow or signer repository, source
ref/digest, OIDC issuer and whether self-hosted runners are
acceptable.
gh attestation verify artifact.tar --repo acme/widget --signer-workflow acme/widget/.github/workflows/release.yml --source-ref refs/heads/main --deny-self-hosted-runners
A production policy may prefer a release tag or exact source digest
rather than main. Branch trust can be appropriate if
branch protections/rulesets and workflow ownership are strong; a
source digest is stricter for one release but requires the
deployment system to know the expected commit. Choose constraints
from the release model, not by copying flags.
5. Central reusable builders and ownership
A central reusable workflow can reduce duplicated build logic and
give consumers one reviewed builder identity. GitHub documentation
currently describes reusable workflows plus artifact attestations as
a way to help achieve SLSA v1 Build Level 3. With cross-repository
reusable workflows, the signer is the reusable workflow
repository/path; verification therefore needs
--signer-repo or --signer-workflow.
6. GitHub feature boundaries versus SLSA
| Layer | Responsible system | Do not conflate it with |
|---|---|---|
| Git source/ref | Git + GitHub repository governance | Artifact digest or build environment. |
| GitHub Actions identity | Hosted CI execution/OIDC context | External cloud identity or universal software trust. |
| Artifact attestation | GitHub/Sigstore signed evidence | Code scanning, secret scanning or SBOM completeness. |
| SLSA Build level | Broader supply-chain specification | A GitHub subscription tier or certification badge. |
| External registry/deployer | Distribution/runtime policy boundary | GitHub repository settings unless integrated explicitly. |
Current SLSA v1.2 still defines Build L1/L2/L3, while GitHub’s artifact-attestation docs specifically phrase their product guidance in SLSA v1.0 terms. A careful production claim should name the SLSA version and track evaluated, document which requirements are supplied by GitHub versus producer workflow design, and avoid implying application-security certification.
7. Worked decision: Atlas Relay release pipeline
| Criterion | Option A: repo-local build | Option B: central reusable builder | Decision reasoning |
|---|---|---|---|
| Maintainability | Each repo owns build YAML | One platform workflow | Central wins if many repos share the same release contract. |
| Security | Repository maintainers can change builder | Builder changes can require platform-owner review | Central can narrow signer identity, but compromise blast radius is larger. |
| Governance | Policy replicated per repo | One reviewed provenance contract | Central generally easier to audit. |
| Reliability | Failure isolated to one repo | Shared outage affects many repos | Repo-local has smaller availability blast radius. |
| Compatibility | Maximum repo customization | Interface must cover supported build types | Choose based on product diversity. |
| Cost | Similar standard runner cost for public path | Platform engineering overhead | Attestation storage/verification is not the main cost driver; maintenance is. |
Atlas Relay chooses a central reusable builder for release artifacts, pins/controls changes to that builder, requires provenance + SPDX SBOM predicates, and verifies both at deployment. Development/test artifacts are not attested because nobody consumes them across a trust boundary.
8. Minimal production policy template
artifact_policy:
subject: "exact bytes or OCI digest"
required_predicates:
- "https://slsa.dev/provenance/v1"
- "https://spdx.dev/Document/v2.3"
signer:
repository: "acme/build-platform"
workflow: ".github/workflows/release.yml"
source:
allowed_refs: ["refs/heads/main", "refs/tags/v*"]
runners:
self_hosted_allowed: false
verification_points:
- publish
- production_deploy
exception:
owner: "supply-chain-security"
expires: "required"
evidence: "required"
This YAML is a policy design fixture, not a GitHub-native policy file. Its value is forcing the organization to name trust assumptions explicitly before encoding them in a deployment system or policy engine.
Knowledge check
Should a container consumer verify the tag or the digest?
Use the immutable image digest as the subject identity. Tags are useful selectors but may be mutable.
Why might provenance verification at build time still be insufficient?
It does not protect the later distribution/deployment boundary from substitution. The consumer should independently verify the bytes it receives.
When does an SBOM add value beyond provenance?
When policy needs component/dependency/license/incident-impact inventory. Provenance tells how the artifact was built, not its complete component list.
What changes when a reusable workflow signs the attestation?
The signer identity is the reusable workflow; verification should constrain the signer workflow/repository rather than assuming the caller workflow signed it.
How should a team state a SLSA claim?
Name the evaluated SLSA version/track/level and evidence/architecture. Do not equate enabling a GitHub feature with universal certification.
Summary
Choose subjects from what consumers actually install/run, predicates from policy questions, and verification points from trust-boundary crossings. Constrain authenticated builder identity as narrowly as your release model permits. GitHub supplies a strong attestation mechanism, but your workflow architecture, SBOM quality and consumer enforcement determine whether the evidence reduces risk. Next you will diagnose realistic ways those pieces fail.
Official references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.