Skip to main content
RunBook Academy

Git, CI/CD & GitOpsLXV · Software Supply Chain SecurityArtifactTrust

Artifact trust and content-addressing — digests, signing, the registry as trust store

Advanced⏱ ~25 mingit

What you'll learn

  • Recognise the registry as the trust store between the build and the deployment
  • Distinguish a tag reference from a digest reference and the threat model of each
  • Verify an artifact signature with cosign before deploying it
  • Recognise what the signature attests (the bytes) and what it does not (the runner, the source)

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.

The registry is the trust store between the build and the deployment. The build writes the artifact and the attestation; the deployment reads the artifact and the attestation. The artifact identified by digest is verifiable; the artifact identified by tag is mutable. The signature on the artifact binds the bytes to the publisher identity. The verification that the signature is from the publisher the deployment trusts is the gate. cosign verify is the gate.

The registry as the trust store

A container registry is more than a file store. A registry is the trust store that holds:

  • The artifact, identified by digest. The digest is the SHA-256 of the artifact’s contents. The digest is content-addressable: the same bytes always produce the same digest. An artifact identified by digest is immutable.
  • The artifact, identified by tag. The tag is a mutable label that points to a digest. A tag can be re-pointed to a different digest. An artifact identified by tag is not immutable.
  • The signature. A signature over the digest, applied by the publisher’s identity. The signature is what binds the bytes to the publisher.
  • The attestation. A document (e.g., SLSA provenance, SBOM) attached to the artifact and signed by the publisher. The attestation is what the deployment verifies in addition to the signature.
flowchart LR
    A["Build: artifact bytes"] --> B["Compute digest"]
    B --> C["Push to registry"]
    A --> D["Sign with publisher key"]
    D --> E["Signature in registry"]
    A --> F["Generate attestation"]
    F --> G["Sign attestation"]
    G --> H["Attestation in registry"]
    I["Deployment: pull by digest"] --> J["cosign verify"]
    J --> K["Signature valid?"]
    K --> L["Deploy"]
    K --> M["Reject"]

The diagram shows the two paths: the build writes the bytes, the digest, the signature, and the attestation; the deployment reads the digest, verifies the signature, and rejects the artifact if verification fails. The registry is the trust store that holds both halves; the deployment is the verification step.

cosign verify —keyless

The cosign tool signs and verifies container artifacts. The verify command reads the signature from the registry, checks the signature against a public key, and exits zero if the signature is valid. The deployment pipeline runs the verify command before deploying the artifact.

DIGEST=$(crane digest registry.example.com/app:v1.2.3)
cosign verify --keyless image:$DIGEST

The command resolves the tag to a digest, then verifies the signature on the artifact identified by the digest. The --keyless flag uses the Sigstore Fulcio certificate authority: the publisher signed the artifact using a short-lived certificate bound to an OIDC identity (e.g., the GitHub Actions workflow). The verifier checks the certificate against the Fulcio CA and the OIDC identity. The exit code is zero if the signature is valid; the deployment script chains the check and fails if the exit code is non-zero.

The --keyless flag is the production pattern because it removes the long-lived signing key from the trust path. The publisher identity is an OIDC identity issued by the build platform, not a key the runner holds. The verification is a check against the Fulcio CA and the OIDC provider; the verifier does not need the publisher’s public key because the certificate is short-lived and tied to the identity.

The verification chain

The verification at the artifact boundary is a chain of checks. The chain is:

  1. Resolve the tag to a digest. The deployment script resolves the tag at promotion time and records the digest. The deployment uses the digest, not the tag.
  2. Verify the signature on the artifact. cosign verify reads the signature from the registry and checks it against the trusted identity. The exit code is zero if the signature is valid.
  3. Verify the attestation. cosign verify-attestation reads the provenance attestation and checks it against the trusted builder identity. The exit code is zero if the attestation is valid.
  4. Verify the policy. The deployment checks the attestation’s payload against the policy: the build was from a protected branch, the SBOM contains no disallowed dependency, the builder identity is in the allow list.
  5. Deploy. The deployment script applies the artifact only after all four checks pass.

The chain is the production discipline. A deployment that skips a step is a deployment that has a missing link. The attacker at the artifact boundary exploits the missing link.

Production discipline

  1. Pin by digest, always. The deployment references the digest, not the tag. The tag is resolved at promotion time and discarded.
  2. Sign every artifact with the publisher identity. The signature uses a keyless flow (Fulcio) or a key held by the build platform, not the runner.
  3. Verify the signature before deploying. cosign verify is the gate. The deployment fails if verification fails.
  4. Verify the provenance. The signature attests the bytes; the provenance attests the build. The deployment checks both.
  5. Record the verification result. The deployment log records the digest, the verification result, and the identity. The audit answers “what was deployed, by whom, under what signature”.

Cross-course references

  • Git, CI/CD & GitOps — Part LXV-01 (Trust Boundaries) maps the artifact boundary this lesson covers.
  • Git, CI/CD & GitOps — Part XLV-02 (Digests) covers the content-addressing model in detail.
  • Git, CI/CD & GitOps — Part XLV-06 (Provenance) covers the attestation that accompanies the signature.
  • Git, CI/CD & GitOps — Part LII-06 (OCI Packaging) covers the OCI distribution model the registry implements.

Quiz

Knowledge check · 4 questions

  1. Q1. What does the signature on an artifact attest?

  2. Q2. A deployment that references an artifact by tag is a deployment that pins the bytes it will run.

  3. Q3. Name the five steps of the verification chain at the artifact boundary.

  4. Q4. Identify the gap in the team's artifact trust posture and the rule that closes it.

    Team T publishes a container image to a public registry. The image is tagged `v1.2.3`. The deployment pipeline pulls the image by tag and deploys it. The artifact is not signed. An attacker compromises the registry's write credentials and pushes a backdoored image under the same tag `v1.2.3`. The next deployment pulls the backdoored image because the tag is now re-pointed. The backdoored image runs in production. The team discovers the attack six weeks later when the audit shows the digest running in production does not match the digest originally published.

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