Software Securityhome
Fix a findingSearch
Phase 5 · Release

Artifact signing

Artifact signing attaches a cryptographic signature to a release file or container image, so anyone can check who produced it and that its bytes have not changed since. Verification checks that signature against a trust policy naming the identities allowed to sign, before the artifact is installed or deployed.

Between your build and your servers sit registries, mirrors and CDNs, and a tag can be moved to different bytes. Verifying the digest against the expected signer stops a substituted image at deploy time. A signature alone proves little: anyone can make a valid keyless Sigstore signature with their own identity, so the check must also pin who signed, such as your release workflow on main.

Who
The release pipeline signs; the platform or SRE team owns the trust policy and the checks at deploy and admission
When
Sign in the build job that produced the artifact; verify at promotion, at deploy and when the cluster admits a workload
How often
Every release artifact, every time; review the trust policy whenever release workflows, keys or signers change
You end up with
A signature or Sigstore bundle per artifact, a written trust policy, and deploy logs showing the verified digest and signer

Do this

  1. Choose a signing method

    In CI, keyless signing with Sigstore cosign avoids a stored key: the job's OIDC token gets a Fulcio certificate valid for 10 minutes, and the signature is recorded in the Rekor transparency log. Notation, from the Notary Project, signs with X.509 certificates checked against a trust store you manage. Either way, sign in the same job that built the artifact.

  2. Sign the digest, not a tag

    Sign the immutable digest, such as ghcr.io/acme/api@sha256:..., and later deploy that same digest: a tag can be moved to other bytes. For files, write a Sigstore bundle beside the artifact with cosign sign-blob --bundle, so verifiers get the certificate, signature and log evidence in one file.

  3. Write the trust policy

    Record which identities may sign which artifacts. For keyless signing that is the exact workflow identity and OIDC issuer, such as https://github.com/acme/api/.github/workflows/release.yml@refs/heads/main from https://token.actions.githubusercontent.com; for Notation, a trust store and trustedIdentities. Keep the policy in protected configuration, not beside the artifact.

  4. Verify before every deploy

    In the promotion or deploy job, run cosign verify on the digest with --certificate-identity and --certificate-oidc-issuer (or notation verify), and fail on any error. Pin CI claims too where they exist, such as --certificate-github-workflow-trigger push. If you require build provenance, check it in the same step (SBOM and provenance).

  5. Enforce the same policy at admission

    Anyone who can create Pods directly skips the deploy job, so enforce the identities in the cluster with an admission controller such as Sigstore policy-controller or Kyverno verifyImages. Policy-controller checks namespaces labeled policy.sigstore.dev/include: "true" and, by default, rejects images that match no policy.

  6. Test the policy with near misses

    Prove the check discriminates: an unsigned image, an image signed by another workflow, the right signer on different bytes and the right identity from another issuer must all be rejected, while the real release passes. Keep these cases as tests of the deploy pipeline.

  7. Publish how to verify, and plan for outages

    Publish the verify command and expected identity for your customers: SSDF PS.2.1 asks you to make integrity verification information available to acquirers. Decide in advance what happens when the verifier is down: a recorded, expiring emergency path for one digest, never a silent global bypass.

Done when

The deploy step rejects unsigned artifacts and artifacts signed by an unexpected identity.

Mark it in the gap check

Common mistakes

  • Checking only that an artifact is signed. Anyone can get a valid keyless signature for their own malicious image, so verify the signer's identity and issuer as well.
  • Allowing a broad identity, such as any workflow in the organization or an unanchored regular expression. An unrelated repository's workflow can then sign your release; if a pattern is unavoidable, anchor it with ^ and $.
  • Verifying a tag, then deploying the tag. It can move between the two steps, so what runs is not what you checked.
  • Reading a valid signature as proof the software is safe. The SolarWinds Orion and 3CX releases were validly signed even though their builds were compromised; add provenance and Pipeline hardening.
  • Verifying only in a CI job. A manual push or a direct kubectl apply bypasses it unless admission enforces the same policy.
  • Keeping a long-lived signing key on build runners or laptops. A stolen key signs anything; OWASP SAMM's top build level keeps signing on a separate server that never exposes the signing certificate.

Keyless, key pair or certificate?

All three can enforce the same rule, that only your release pipeline signs your releases. They differ in what you must protect and what the verifier pins.

Keyless, key pair or certificate?: table
ApproachSigning identityWhat the verifier pins
Sigstore keyless (cosign)A Fulcio certificate valid for 10 minutes, bound to the CI job's OIDC identityCertificate identity and OIDC issuer, plus CI claims such as trigger and repository
Key pair (cosign --key)A long-lived private key you must protect, rotate and be able to revokeThe public key, from a file, a KMS URI or a Kubernetes Secret
Notary Project (notation)An X.509 certificate chain from a certificate authority you trustA trust store and trustedIdentities in a trust policy, scoped to registries

Tools and guides

Standards

NIST SSDF 1.1
PS.2 Provide a Mechanism for Verifying Software Release Integrity

Sources

  1. Sigstore: Verifying signatures
  2. cosign verify reference
  3. Sigstore: Certificate authority overview
  4. Sigstore: Policy controller overview
  5. Notary Project: Sign and verify a container image with Notation
  6. Kyverno: Verify images rules
  7. OWASP SAMM: Secure Deployment, Deployment Process stream
  8. OWASP SAMM: Secure Build, Build Process stream
  9. NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1. February 2022.

Find your next answer

Type to search. Search runs in your browser.

Searches run in your browser, but the host can infer them from the index files they load. The address shows your search so you can bookmark or share it.