Skip to main content
RunBook Academy

Git, CI/CD & GitOpsFinal · Final AssessmentFinal Review

Supply chain and signing — recap

Advanced⏱ ~28 mingit

What you'll learn

  • Name the five supply-chain trust boundaries and identify which control closes each one
  • Explain why pinning to a digest (not a tag) is the only safe way to reference a third-party artifact
  • Distinguish an SBOM (what is in the artifact) from a provenance attestation (how the artifact was built)
  • Plan a keyless cosign signing flow with Fulcio and Rekor that an auditor can verify six months later

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.

A supply-chain attack is a substitution attack. Somewhere between the source the engineer wrote and the artifact running in production, an attacker swaps one of the links for one they control. The defense is a chain of attestations: a signed commit, a pinned dependency, an SBOM that names every component, a provenance attestation that names the build, a signed artifact, and a verify step at the deploy boundary that checks every attestation before allowing the artifact to run. Break any link and the consumer is trusting the attacker’s link.

The five trust boundaries

flowchart LR
    A["Source\n(commit)"] -->|pinned?| B["Dependency\n(package)"]
    B -->|pinned?| C["CI build"]
    C -->|attested?| D["Artifact\n(image/binary)"]
    D -->|signed?| E["Deployment"]
    E -->|verified?| F["Runtime"]
    style A fill:#dff
    style B fill:#dff
    style C fill:#dff
    style D fill:#dff
    style E fill:#dff
  • Source. A signed commit, a branch-protection rule, and a CODEOWNERS check. The commit says who wrote the change; the signature says the identity was real.
  • Dependency. A pinned digest, a lockfile, and a dependabot or renovate policy that proposes upgrades as pull requests. The lockfile says exactly which bytes the build used; pinning says those bytes cannot be silently swapped.
  • CI build. An isolated runner, ephemeral, no long-lived credentials, no privileged mode without justification. The runner says the build was not tampered with by a previous job.
  • Artifact. A signed OCI image or binary, with an attached SBOM and provenance attestation. The signature says the artifact came from a specific build; the SBOM says what is inside it; the provenance attestation says how it was built.
  • Deployment. A verifier (admission controller, deploy policy) that checks the signature against the expected identity, checks the SBOM against known vulnerabilities, and rejects anything that does not match. The verifier is the last gate before the artifact runs.

SBOM and provenance — two different questions

The two artifacts an auditor asks for are not the same artifact:

  • SBOM (Software Bill of Materials). A list of every component that went into the artifact. SPDX and CycloneDX are the two standard formats. The SBOM answers “what is in this artifact?” and is the input to a vulnerability scan.
  • Provenance attestation. A signed statement about how the artifact was built: which commit, which builder, which build invocation, with what parameters. SLSA defines the levels; in-toto is the attestation format. The provenance attestation answers “how was this artifact produced?” and is the input to a trust decision.

An SBOM without provenance tells you what is in the artifact but not whether you can trust the build that produced it. A provenance attestation without an SBOM tells you the build was trusted but not what the artifact contains. Both are needed; neither is a substitute for the other.

The Sigstore stack

The Sigstore stack is the modern default for artifact signing:

flowchart LR
    A["OIDC identity\n(GitHub Actions)"] -->|request certificate| B["Fulcio"]
    B -->|short-lived X.509 cert| C["cosign sign"]
    C -->|signature| D["Rekor\n(transparency log)"]
    D -->|timestamped entry| E["signature + log entry + cert"]
    E -->|verify| F["cosign verify"]
  • Fulcio. Issues a short-lived X.509 certificate binding an OIDC identity (the workflow that requested it) to a public key. The certificate is valid for roughly 30 minutes.
  • cosign. Signs the artifact (or its digest) with the private key. The signature is meaningless without the Fulcio-issued certificate that binds the key to the OIDC identity.
  • Rekor. A transparency log that records every signing event. The log entry is a tamper-evident timestamped record that the signature existed at a specific time.

The non-obvious property is that no long-lived key exists. The signing key is generated for a single signing event, bound to an OIDC identity that is valid for the duration of one workflow run, and recorded in the transparency log. An auditor verifying the signature six months later checks the Fulcio certificate against the OIDC provider’s published keys, checks the Rekor log entry against the log’s signed tree head, and concludes that the signature was produced by the named workflow at the named time. There is no key to rotate, no key to revoke, no key to leak.

Production discipline

The five rules that recur across every supply-chain control:

  1. Pin to digest, never to tag. A tag is a mutable pointer; a digest is a content address. Production references must be digests.
  2. Lockfile in, lockfile out. Every build reads a lockfile that names exact versions and digests. Mutable references at build time are mutable references in the artifact.
  3. Sign in CI, verify at deploy. The signing happens once; the verification happens every time the artifact runs.
  4. SBOM and provenance are different artifacts. Both must be produced, both must be signed, both must be stored alongside the artifact.
  5. Keyless by default. Long-lived signing keys in CI are a control failure. Sigstore keyless with Fulcio and Rekor is the modern default; self-managed keys are reserved for the cases where the trust root has to outlive the OIDC provider.

Cross-course references

  • Kubernetes for Production Sysadmins — Admission controllers (Kyverno, OPA Gatekeeper) are the deployment-side verifier that turns a cosign signature into a control.
  • Linux for Production Sysadmins — Package verification with rpm --checksig and dpkg-sig is the operating-system analogue of cosign verification.

Quiz

Knowledge check · 4 questions

  1. Q1. A container image is referenced in a Kubernetes manifest as `myorg/api:v3.2.7`. An attacker compromises the upstream registry and re-pushes `v3.2.7` with a malicious payload. What is the consequence for a cluster that pulls the image on next pod restart?

  2. Q2. An SBOM and a provenance attestation answer different questions, and a defense that produces only one of them is incomplete.

  3. Q3. Name the three components of the Sigstore stack and the role each one plays in a keyless signing flow.

  4. Q4. A team has been producing SBOMs in CI but has never enabled signing or verify-on-deploy. The auditor asks for evidence that the SBOM has not been tampered with after the build. Walk through the controls that must be added, in order, to make the SBOM trustworthy.

    The team runs a GitHub Actions pipeline that builds a container image with BuildKit, generates a CycloneDX SBOM with `syft`, attaches the SBOM to the image with `syft attest`, and pushes the image to GHCR. There is no cosign signing, no Rekor entry, and no admission controller in the cluster that verifies signatures or SBOMs. The SBOM is attached to the image but is not itself signed.

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