Safeguard
Container Security

Image Signing with Cosign and Sigstore

A container image tag proves nothing about who built the image or whether it was tampered with. Cosign and Sigstore fix that with cryptographic signatures and a public transparency log — here is how to sign, verify, and enforce.

Marcus Chen
Cloud Security Engineer
5 min read

Ask a cluster to run myapp:v1.4.0 and it will happily pull whatever bytes currently live behind that tag — with no way of knowing who built them, from what source, or whether someone swapped the image after it was pushed. Tags are mutable labels, not identities. That gap is precisely what supply-chain attackers exploit: compromise a registry or a build pipeline, repoint a tag, and every cluster that trusts the tag runs your malware. Image signing closes the gap by attaching a cryptographic signature that proves an image's origin and integrity, and by enforcing at admission that only signed images run. Sigstore, and its cosign CLI, made this practical for everyone by removing the traditional pain of key management. This guide covers signing, keyless signing, provenance, and enforcement.

What Sigstore actually is

Sigstore is a set of open-source components, now widely adopted across the container ecosystem, that together make signing usable:

  • cosign — the CLI that signs and verifies container images and other OCI artifacts.
  • Fulcio — a certificate authority that issues short-lived signing certificates bound to an identity (an email, or a workload's OIDC token).
  • Rekor — a public, tamper-evident transparency log that records signing events so anyone can audit that a signature existed at a point in time.

The signature and attestations are stored right alongside the image in the OCI registry, so there is no separate infrastructure to run. By 2026 these components are broadly relied on across the container ecosystem, and cosign has become the de facto tool for signing not just images but Helm charts, SBOMs, and arbitrary OCI artifacts — which means the same workflow you learn here extends to the rest of your supply chain.

Signing with a key pair

The simplest model uses a cosign key pair. Generate one, sign the image by digest, and push:

cosign generate-key-pair
# Always sign by digest — a tag can move, a digest cannot
cosign sign --key cosign.key \
  registry.example.com/myapp@sha256:abc123...

Verification checks the signature against the public key:

cosign verify --key cosign.pub \
  registry.example.com/myapp@sha256:abc123...

The catch with key-based signing is the same as with any signing key: you have to store, rotate, and protect the private key, and a leaked key undermines everything.

Keyless signing — the modern default

Keyless signing removes the long-lived private key entirely. Instead, cosign requests a short-lived certificate from Fulcio, bound to an OIDC identity, signs with an ephemeral key, and records the event in Rekor. In CI this identity is the pipeline's own OIDC token, so the signature proves which workflow produced the image:

# In GitHub Actions with id-token: write permission — no stored key
COSIGN_EXPERIMENTAL=1 cosign sign \
  registry.example.com/myapp@sha256:abc123...

Verification then asserts who signed it and from which issuer, which is far stronger than "some key we hold signed it":

cosign verify \
  --certificate-identity-regexp 'https://github.com/myorg/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  registry.example.com/myapp@sha256:abc123...

Because the certificate is short-lived and the event is logged in Rekor, there is no signing key to steal and every signature is publicly auditable.

Go further: sign provenance, not just the image

A signature proves the image was not tampered with after signing. Provenance proves how it was built. cosign can attach SLSA provenance and SBOM attestations, so a verifier can require that an image was built by a specific pipeline from a specific source commit:

# Attach an SBOM as a signed attestation
cosign attest --predicate sbom.cdx.json \
  --type cyclonedx \
  registry.example.com/myapp@sha256:abc123...

Now verification can demand not just a signature but a matching, signed SBOM and build provenance — the foundation of a real SLSA posture.

Enforce it at admission — signing without verification is theater

Signing images does nothing if the cluster still runs unsigned ones. Close the loop with an admission-time policy engine. The Sigstore policy-controller, or Kyverno's image-verification rules, reject any image that lacks a valid signature from an expected identity:

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

With this in place, an image that is not signed by your pipeline simply cannot be scheduled.

Rollout checklist

  • Sign every image by digest in CI, using keyless signing bound to the pipeline's OIDC identity
  • Attach signed SBOM and SLSA provenance attestations
  • Store signatures in the registry alongside images (the cosign default)
  • Deploy an admission policy that verifies signature and identity, in Enforce mode
  • Start policies in Audit on existing namespaces to find unsigned workloads before you block them
  • Verify third-party base images too, or mirror and re-sign them under your own identity

How Safeguard helps

Signing and provenance are only as useful as the metadata behind them, and that metadata is what Safeguard produces and tracks. SBOM Studio generates the CycloneDX and SPDX bills of materials you attach as signed attestations, and diffs them release over release so a signed image with silently changed dependencies does not slip through. Container security scanning ties each signed image to its real vulnerability posture, so "signed" never gets mistaken for "safe," and the Safeguard CLI runs signing, SBOM generation, and verification checks directly in your pipeline. Safeguard's IaC scanning confirms your admission policies actually enforce verification rather than running in permissive mode. Review options on the pricing page.

A tag is a promise; a signature is proof. Create a free Safeguard account or read the documentation to build signing and provenance into your pipeline.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.