Skip to content

DOMAIN:SUPPLY_CHAIN:PROVENANCE

OWNER: julian, pol
ALSO_USED_BY: koen, victoria, ashley
UPDATED: 2026-03-26
SCOPE: build provenance, artifact signing, and verification for all projects


OVERVIEW

Build provenance answers: who built this, from what source, on what platform, with what inputs?
Without provenance, any artifact could be tampered with between build and deployment.
SLSA framework provides maturity levels for provenance trustworthiness.
Sigstore/cosign provide the practical signing and verification toolchain.

EU CRA will require vulnerability handling and traceability from Sep 2026.
Provenance is the mechanism that makes traceability possible.


SLSA FRAMEWORK (Supply-chain Levels for Software Artifacts)

CURRENT VERSION: v1.1 (2025)

SLSA defines progressive levels of build integrity assurance.
Each level builds on the previous one.

LEVEL 0 — NO SLSA

NO provenance exists.
BUILD on local developer machine.
NO verification possible.
ACCEPTABLE_FOR: local development only — never for production artifacts.

LEVEL 1 — PROVENANCE EXISTS

BUILD process documented.
PROVENANCE generated automatically describing how artifact was built.
PROVENANCE available to consumers.

REQUIREMENTS:
- build runs on defined platform (CI/CD)
- provenance generated automatically (not manually written)
- provenance includes: source repo, commit, builder, build timestamp

ACHIEVABLE_WITH: any CI/CD system + SBOM generation.
EFFORT: minimal — add provenance generation step to pipeline.

LEVEL 2 — HOSTED BUILD + SIGNED PROVENANCE

BUILD on hosted platform (not developer machine).
PROVENANCE signed (tampering detectable).
SIGNING provides evidence of which build service produced the artifact.

REQUIREMENTS (L1 plus):
- hosted build service (GitHub Actions, GitLab CI, Jenkins on managed infra)
- provenance cryptographically signed
- signature verifiable by consumers

ACHIEVABLE_WITH: GitHub Actions + Sigstore cosign.
EFFORT: moderate — add signing step to pipeline.

LEVEL 3 — HARDENED BUILD PLATFORM

BUILD platform hardened against insider threats.
PROVENANCE non-falsifiable (even compromised build admin cannot forge).
BUILD runs in isolated environment.

REQUIREMENTS (L2 plus):
- isolated build environments (ephemeral, fresh per build)
- non-falsifiable provenance (signed by platform, not user)
- build platform access controls (admins cannot modify build output)
- audit trail for build platform configuration changes

ACHIEVABLE_WITH: Tekton Chains + Sigstore, GitHub Actions SLSA generator.
EFFORT: significant — requires hardened CI infrastructure.

LEVEL 4 — TWO-PERSON REVIEW + HERMETIC BUILD

BUILD is hermetic (all inputs declared, no network access during build).
SOURCE requires two-person review before build.
PROTECTS against compromised individual developer.

REQUIREMENTS (L3 plus):
- two-person code review enforced before merge
- hermetic build (no network access, all dependencies pre-fetched)
- reproducible build (same inputs always produce same output)

ACHIEVABLE_WITH: Bazel/Nix + strict branch protection + Tekton.
EFFORT: very high — significant infrastructure investment.

GE TARGET

IMMEDIATE: SLSA Level 2 for all production artifacts.
12_MONTH: SLSA Level 3 for client-facing deployments.
LEVEL_4: not currently justified — revisit when enterprise clients require it.


CONTAINER IMAGE SIGNING (cosign / Sigstore)

WHAT IS SIGSTORE

Sigstore is an open-source project providing keyless signing infrastructure.
"Keyless" = no long-lived private keys to manage.
Uses short-lived certificates tied to OIDC identity (GitHub, Google, etc.).

COMPONENTS:
- FULCIO: certificate authority — issues short-lived signing certificates
- REKOR: transparency log — append-only record of all signatures
- COSIGN: CLI tool — signs and verifies container images, SBOMs, attestations

HOW COSIGN WORKS

  1. developer/CI triggers cosign sign
  2. cosign requests certificate from Fulcio (proves identity via OIDC)
  3. Fulcio issues short-lived certificate (valid minutes)
  4. cosign signs artifact with certificate
  5. signature recorded in Rekor transparency log
  6. signature stored in OCI registry alongside image (same repo, different tag)

SIGNING CONTAINER IMAGES

# Sign an image (keyless — uses OIDC identity from CI)  
cosign sign ghcr.io/ge-bootstrap/admin-ui:v1.2.3  

# Sign with key (if keyless not available)  
cosign generate-key-pair  
cosign sign --key cosign.key ghcr.io/ge-bootstrap/admin-ui:v1.2.3  

# Attach SBOM to image  
cosign attach sbom --sbom sbom.cyclonedx.json ghcr.io/ge-bootstrap/admin-ui:v1.2.3  

# Sign the attached SBOM  
cosign sign --attachment sbom ghcr.io/ge-bootstrap/admin-ui:v1.2.3  

VERIFYING CONTAINER IMAGES

# Verify keyless signature (checks Rekor + Fulcio)  
cosign verify ghcr.io/ge-bootstrap/admin-ui:v1.2.3 \  
  --certificate-identity=workflow@github.com \  
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com  

# Verify with key  
cosign verify --key cosign.pub ghcr.io/ge-bootstrap/admin-ui:v1.2.3  

CI/CD INTEGRATION

GITHUB_ACTIONS: sigstore/cosign-installer action + keyless signing via OIDC
GITLAB_CI: cosign binary + OIDC token from GitLab
LOCAL_K3S: key-based signing (no OIDC provider available for local builds)


ARTIFACT ATTESTATION

IN-TOTO ATTESTATION FORMAT

STANDARD: in-toto — framework for software supply chain integrity
ATTESTATION: signed statement about an artifact (who built it, how, from what)
FORMAT: JSON envelope with type, subject (artifact hash), and predicate (claims)

SLSA PROVENANCE ATTESTATION

PREDICATE_TYPE: https://slsa.dev/provenance/v1
CONTENTS:
- buildDefinition: build type, external parameters (source repo, commit)
- runDetails: builder identity, build metadata, timestamps
- materials: all inputs (source, dependencies)

GITHUB ATTESTATIONS (native)

GitHub now provides built-in attestation support:

- uses: actions/attest-build-provenance@v2  
  with:  
    subject-name: ghcr.io/ge-bootstrap/admin-ui  
    subject-digest: sha256:abc123...  
GENERATES: SLSA v1 provenance attestation, signed by GitHub's Sigstore instance.
STORES: in GitHub's attestation store, verifiable via gh attestation verify.

CUSTOM ATTESTATIONS

For claims beyond provenance (vulnerability scan results, licence compliance):

cosign attest --predicate scan-results.json \  
  --type https://ge.nl/attestation/vuln-scan/v1 \  
  ghcr.io/ge-bootstrap/admin-ui:v1.2.3  


REPRODUCIBLE BUILDS

WHAT

Same source code + same build environment = identical binary output, every time.
Allows independent verification that a binary was built from claimed source.

WHY

WITHOUT reproducibility: must trust build infrastructure.
WITH reproducibility: anyone can verify binary matches source.
REQUIRED for SLSA Level 4, valuable at any level.

CHALLENGES

NON-DETERMINISM_SOURCES:
- timestamps embedded in artifacts (build date in binary)
- random values (UUIDs, nonces generated at build time)
- filesystem ordering (directory listing order varies)
- build path differences (absolute paths in debug info)
- floating dependency versions (even with lock file — registry availability)

PRACTICAL STEPS

CHECK: pin all dependency versions (lock files committed)
CHECK: pin base image by digest (not tag)
CHECK: use SOURCE_DATE_EPOCH for timestamps
CHECK: avoid embedding build-time metadata (or make it deterministic)
CHECK: use deterministic build tools (Bazel, Nix, ko for Go)
CHECK: document build environment precisely (Dockerfile = build env definition)

GE STATUS

FULL_REPRODUCIBILITY: not yet achieved — significant effort.
PRACTICAL_APPROACH: pin dependencies, pin base images by digest, use Docker multi-stage builds.
GOAL: bit-for-bit reproducibility for critical client deliverables by 2027 (CRA driver).


PROVENANCE VERIFICATION IN CI/CD

DEPLOY-TIME VERIFICATION

Before deploying any artifact to production:

# Verify image signature  
cosign verify --certificate-identity=... --certificate-oidc-issuer=... $IMAGE  

# Verify SLSA provenance  
cosign verify-attestation --type slsaprovenance $IMAGE  

# Verify SBOM attestation  
cosign verify-attestation --type cyclonedx $IMAGE  

KUBERNETES ADMISSION CONTROL

TOOL: Kyverno or OPA/Gatekeeper
PURPOSE: enforce that only signed, attested images can deploy to cluster

KYVERNO_POLICY_EXAMPLE:

apiVersion: kyverno.io/v1  
kind: ClusterPolicy  
metadata:  
  name: require-signed-images  
spec:  
  validationFailureAction: Enforce  
  rules:  
  - name: verify-signature  
    match:  
      resources:  
        kinds: [Pod]  
    verifyImages:  
    - imageReferences: ["ghcr.io/ge-bootstrap/*"]  
      attestors:  
      - entries:  
        - keyless:  
            issuer: https://token.actions.githubusercontent.com  
            subject: workflow@github.com  

VERIFICATION CHAIN

SOURCE → BUILD (signed provenance) → ARTIFACT (signed image + SBOM) → DEPLOY (verified)  

EVERY link in chain must be verifiable.
BREAK any link = cannot trust the artifact.


GhostAction ATTACK (2025) — LESSONS

WHAT HAPPENED

Attackers compromised widely-used third-party GitHub Action.
Modified workflow code to exfiltrate CI/CD secrets.
Action was pinned by tag (@v1) not commit SHA.
Every repository using @v1 automatically pulled compromised version.

LESSONS

RULE: pin GitHub Actions by commit SHA, not tag.

# BAD — tag can be moved to malicious commit  
- uses: actions/checkout@v4  

# GOOD — pinned to specific commit  
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1  

TOOL: Renovate/Dependabot can manage SHA pinning and update PRs.
VERIFY: action provenance before adopting new Actions.


ADOPTION ROADMAP

PHASE 1 (immediate) — SLSA Level 1

  • [ ] generate SBOM at every build (syft/cdxgen)
  • [ ] store SBOM alongside build artifacts
  • [ ] document build process in CI config

PHASE 2 (3 months) — SLSA Level 2

  • [ ] sign container images with cosign (keyless in CI, key-based for local k3s)
  • [ ] sign SBOM attestations
  • [ ] generate SLSA provenance attestation
  • [ ] pin GitHub Actions by SHA

PHASE 3 (6 months) — SLSA Level 3

  • [ ] ephemeral build environments (fresh runners per build)
  • [ ] deploy-time signature verification (Kyverno or equivalent)
  • [ ] non-falsifiable provenance (GitHub/GitLab native attestation)

READ_ALSO: domains/supply-chain/index.md, domains/supply-chain/sbom.md, domains/supply-chain/vulnerability-management.md