Container Image Signing Tools Compared: Cosign vs Notation vs GPG

Why Container Image Signing Matters

Every time you pull a container image and deploy it into production, you’re placing implicit trust in that artifact. But how do you verify that the image hasn’t been tampered with? How do you confirm it was actually built by your CI/CD pipeline and not injected by an attacker who compromised your registry?

Container image signing solves this problem by attaching a cryptographic signature to your images. Before deployment, your orchestrator or admission controller can verify that signature, ensuring only trusted, authenticated images enter your environment. This is a cornerstone of software supply chain security and a requirement in frameworks like SLSA and NIST SSDF.

But signing tools are not all equal. The three dominant approaches today — Cosign (part of the Sigstore project), Notation (the Notary v2 client), and GPG (the traditional approach) — each come with radically different trade-offs in key management, CI/CD integration, and ecosystem compatibility.

In this guide, we’ll do a deep, hands-on comparison of all three so you can make the right choice for your pipelines.

Cosign and the Sigstore Ecosystem

Overview

Cosign is the container image signing tool from the Sigstore project, which is now a graduated project under the Linux Foundation. Sigstore’s mission is to make software signing ubiquitous by removing the biggest barrier: key management.

Cosign stores signatures as OCI artifacts directly alongside the signed image in the same registry. This means there is no separate signature storage system to maintain — your existing container registry (Docker Hub, GitHub Container Registry, AWS ECR, Google Artifact Registry, etc.) serves double duty.

Keyless Signing with Fulcio and Rekor

Cosign’s most revolutionary feature is keyless signing. Instead of managing long-lived signing keys, Cosign integrates with two services:

  • Fulcio — A certificate authority that issues short-lived signing certificates based on an OpenID Connect (OIDC) identity. In a CI/CD context, this is typically the identity token from your pipeline provider (GitHub Actions OIDC, GitLab CI OIDC, etc.).
  • Rekor — An immutable transparency log that records every signing event. This provides a tamper-evident audit trail of who signed what and when.

With keyless signing, the workflow looks like this:

  1. Your CI pipeline requests an OIDC token from the pipeline provider.
  2. Cosign presents that token to Fulcio, which issues a short-lived certificate binding the pipeline identity to an ephemeral key pair.
  3. Cosign signs the image digest with the ephemeral private key.
  4. The signature and certificate are recorded in Rekor’s transparency log.
  5. The ephemeral private key is discarded — it only existed for seconds.

This eliminates the entire class of problems around key rotation, key storage, and key compromise. There is no long-lived secret to protect.

Key-Based Signing

Cosign also supports traditional key-pair signing for environments where keyless is not feasible (air-gapped networks, regulatory requirements for specific key custody). You generate a key pair with cosign generate-key-pair and sign with cosign sign --key cosign.key.

CI/CD Integration Example: GitHub Actions

# .github/workflows/sign.yml
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # Required for keyless signing
      packages: write   # Required to push signatures to GHCR
    steps:
      - uses: sigstore/cosign-installer@v3

      - name: Sign the container image (keyless)
        env:
          COSIGN_EXPERIMENTAL: 1
        run: |
          cosign sign --yes ghcr.io/myorg/myapp@sha256:abc123...

      - name: Verify the signature
        run: |
          cosign verify \
            --certificate-oidc-issuer https://token.actions.githubusercontent.com \
            --certificate-identity-regexp https://github.com/myorg/myapp/.github/workflows/* \
            ghcr.io/myorg/myapp@sha256:abc123...

The id-token: write permission is the critical piece — it allows GitHub Actions to mint the OIDC token that Fulcio uses to issue the signing certificate. No secrets to configure, no keys to store. For a hands-on walkthrough, see our Cosign Keyless Signing Lab.

Strengths

  • Keyless signing eliminates key management entirely in CI/CD
  • Transparency log (Rekor) provides an immutable audit trail
  • Native OCI artifact storage — no external signature store needed
  • Rich policy verification with certificate identity matching
  • Broad ecosystem support (Kyverno, OPA Gatekeeper, Kubernetes policy controllers)
  • Active, well-funded open-source community

Limitations

  • Keyless mode requires internet access to Fulcio and Rekor (challenging for air-gapped environments)
  • Verification in air-gapped environments requires mirroring the transparency log
  • Relatively young project compared to GPG (though now stable and graduated)

Notation and Notary v2

Overview

Notation is the CLI client for the Notary v2 specification, a CNCF project backed primarily by Microsoft and AWS. Where Cosign was purpose-built for the Sigstore ecosystem, Notation was designed to integrate with enterprise PKI infrastructure and existing X.509 certificate workflows.

Notation uses COSE (CBOR Object Signing and Encryption) signatures stored as OCI artifacts attached to the signed image using the ORAS (OCI Registry As Storage) specification. Like Cosign, this means signatures live in the OCI registry alongside images.

Key Management with Plugins

Notation uses a plugin architecture for key management. Instead of handling keys directly, it delegates to plugins that interface with external key vaults:

  • Azure Key Vault plugin — Signs using keys stored in Azure Key Vault.
  • AWS Signer plugin — Uses AWS Signer, a fully managed signing service.
  • HashiCorp Vault plugin — Integrates with Vault’s transit secrets engine.

This plugin model is a natural fit for enterprises that already have centralized key management and PKI infrastructure. The signing key never leaves the HSM or cloud KMS — Notation sends the digest to the plugin, and the plugin returns the signature.

Trust Policies and Trust Stores

Notation uses a JSON-based trust policy system for verification. You define which registries, repositories, and images you trust and which certificates or certificate chains are authorized to sign them. This is powerful for enterprise governance scenarios where different teams have different signing authorities.

// trustpolicy.json
{
  "version": "1.0",
  "trustPolicies": [
    {
      "name": "production-images",
      "registryScopes": ["registry.example.com/prod/*"],
      "signatureVerification": {
        "level": "strict"
      },
      "trustStores": ["ca:production-ca"],
      "trustedIdentities": ["x509.subject: CN=prod-signer, O=MyOrg"]
    }
  ]
}

CI/CD Integration Example: GitHub Actions with AWS Signer

# .github/workflows/notation-sign.yml
jobs:
  sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # For AWS OIDC federation
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/signer-role
          aws-region: us-east-1

      - name: Setup Notation
        uses: notaryproject/notation-action/setup@v1

      - name: Install AWS Signer plugin
        run: |
          notation plugin install \
            --url https://d2hvyiie56hcat.cloudfront.net/linux/amd64/plugin/latest/notation-aws-signer-plugin.zip

      - name: Sign the container image
        run: |
          notation sign \
            --plugin com.amazonaws.signer.notation.plugin \
            --id arn:aws:signer:us-east-1:123456789012:/signing-profiles/MyProfile \
            registry.example.com/myapp@sha256:abc123...

Strengths

  • Enterprise-friendly plugin architecture integrates with existing PKI and KMS
  • Rich trust policy framework for granular, registry-scoped verification
  • COSE signature format is a well-established IETF standard
  • Strong backing from Microsoft (Azure) and AWS
  • Designed for organizations with existing X.509 certificate workflows
  • Offline verification is straightforward — just need the trust store certificates

Limitations

  • No keyless signing — you must manage certificates and keys (even if delegated to a KMS)
  • No built-in transparency log equivalent
  • Plugin ecosystem is still growing; fewer plugins than Cosign’s integration points
  • Smaller community and fewer tutorials compared to Cosign
  • Trust policy configuration can be complex for simple use cases

GPG: The Traditional Approach

Overview

GPG (GNU Privacy Guard) is the veteran of the signing world. Long before container-native signing tools existed, GPG was used to sign everything from email to Git commits to Linux packages. Some teams still use GPG to sign container images, particularly through tools like Docker Content Trust (DCT) or by signing image manifests out-of-band.

How GPG Signing Works for Containers

GPG container signing typically follows one of two patterns:

  • Out-of-band signing: Export the image manifest or digest, sign it with gpg --detach-sign, and store the .sig file alongside the image (in a separate artifact store, S3 bucket, or Git repository).
  • Podman/Skopeo integration: Podman and Skopeo have native GPG signature support. Signatures are stored on a separate signature server (a web server serving detached signatures) and verified at pull time using a policy file (/etc/containers/policy.json).

Docker Content Trust (DCT) uses a related but distinct approach based on The Update Framework (TUF), with Notary v1 as the backend. While DCT uses different cryptographic primitives than raw GPG, it shares the same fundamental challenge: long-lived key management.

Key Management Challenges

GPG’s biggest weakness in a CI/CD context is key management:

  • You must generate, distribute, rotate, and revoke long-lived key pairs
  • Private keys need to be securely injected into CI/CD runners as secrets
  • There’s no built-in key escrow or recovery mechanism
  • Key distribution to verifiers (cluster nodes, admission controllers) requires manual processes or a keyserver
  • Key compromise requires emergency rotation across all systems

CI/CD Integration Example: GitLab CI with GPG

# .gitlab-ci.yml
sign-image:
  stage: sign
  image: alpine:latest
  before_script:
    - apk add --no-cache gnupg skopeo
    - echo "$GPG_PRIVATE_KEY" | gpg --batch --import
  script:
    - skopeo copy \
        --sign-by signing-key@myorg.com \
        docker://registry.example.com/myapp:${CI_COMMIT_SHORT_SHA} \
        docker://registry.example.com/myapp:${CI_COMMIT_SHORT_SHA}
  variables:
    GPG_PRIVATE_KEY: $GPG_SIGNING_KEY  # Stored in CI/CD variables

Note how the private key must be stored as a CI/CD secret and injected at runtime — exactly the kind of long-lived secret management that keyless signing was designed to eliminate.

Strengths

  • Battle-tested cryptography — GPG has been audited and hardened for decades
  • Works in fully air-gapped environments with zero external dependencies
  • Familiar to operations teams with Linux/security backgrounds
  • Wide tooling support in the Podman/Skopeo ecosystem
  • Full control over key material (important for certain compliance frameworks)

Limitations

  • Manual, error-prone key management is the single biggest operational burden
  • No keyless mode — private keys must live somewhere accessible to CI/CD
  • No native OCI artifact storage — signatures are stored out-of-band
  • No transparency log for audit trails
  • Signature distribution and discovery is fragmented
  • Docker/containerd do not natively verify GPG signatures (requires Podman/Skopeo or custom tooling)

Side-by-Side Comparison

Feature Cosign (Sigstore) Notation (Notary v2) GPG
Key Management Keyless (OIDC) or static key pairs Plugin-based (KMS, HSM, cloud vaults) Manual PGP key pairs
Keyless Signing Yes (Fulcio + OIDC) No No
Signature Format JSON envelope (in-toto/DSSE) COSE (CBOR) signatures PGP detached signatures
Signature Storage OCI registry (as OCI artifacts) OCI registry (via ORAS) Out-of-band (web server, S3, Git)
OCI Registry Compatibility Excellent — works with all major registries Good — requires OCI 1.1 referrers API support None — signatures stored externally
Transparency Log Yes (Rekor) No (planned) No
CI/CD Integration Excellent — GitHub Actions, GitLab CI, Tekton, native OIDC support Good — GitHub Actions, works with any CI via plugins Manual — requires secret injection of private keys
Kubernetes Policy Kyverno, OPA Gatekeeper, Sigstore Policy Controller Ratify (with Gatekeeper), Kyverno (limited) Requires custom admission webhook
Air-Gapped Support Possible (requires TUF root mirror, Rekor mirror) Yes (straightforward with local trust store) Yes (fully offline-capable)
Ecosystem & Community Large — Linux Foundation, Google, Red Hat, GitHub Growing — CNCF, Microsoft, AWS Mature but declining for container use
Learning Curve Low (keyless) to Medium (key-based with policies) Medium to High (plugins, trust policies, PKI) Medium (familiar tooling, painful operations)
Attestation Support Yes (SBOM, SLSA provenance, custom predicates) Yes (via ORAS attached artifacts) No native support

Decision Matrix: When to Use Which Tool

Choosing the right signing tool depends on your organizational context. Here’s a practical decision framework:

Choose Cosign If:

  • You’re starting fresh with container signing and want the fastest path to production.
  • You use GitHub Actions, GitLab CI, or another OIDC-capable CI/CD system — keyless signing just works.
  • You want a transparency log for audit and compliance without building one yourself.
  • You’re adopting SLSA or in-toto attestations — Cosign has first-class support for attaching SBOMs and provenance metadata.
  • You want broad Kubernetes policy integration with Kyverno or Sigstore Policy Controller.
  • You’re a startup or mid-size organization without a dedicated PKI team.

For a comprehensive guide to Sigstore and keyless signing, see our Sigstore and Cosign Keyless Signing Guide.

Choose Notation If:

  • Your organization has existing PKI infrastructure and X.509 certificate management workflows you want to leverage.
  • You’re heavily invested in Azure or AWS and want native integration with Azure Key Vault or AWS Signer.
  • You need fine-grained trust policies scoped to specific registries, repositories, or teams.
  • Compliance requirements mandate specific key custody (FIPS 140-2, FedRAMP) where keyless signing doesn’t meet the bar.
  • You’re operating in an environment where the Sigstore public infrastructure is not accessible but you have internal PKI.

Choose GPG If:

  • You’re in a fully air-gapped environment with no external service dependencies allowed.
  • You use Podman/Skopeo as your primary container runtime and already have GPG key infrastructure.
  • Regulatory requirements mandate GPG specifically (rare, but some government contracts specify it).
  • You’re signing non-OCI artifacts alongside containers and want a single signing tool.

For most teams building modern cloud-native applications, Cosign with keyless signing is the recommended default. It provides the best security-to-operational-complexity ratio and eliminates the key management burden that causes most signing initiatives to fail in practice.

CI/CD Integration Patterns

Beyond the individual examples above, here are architectural patterns for integrating signing into your pipeline:

Pattern 1: Sign-on-Build (Cosign Keyless)

The simplest pattern. The same pipeline job that builds and pushes the image also signs it. Keyless signing means no secrets to manage:

Build Image → Push to Registry → Cosign Sign (keyless) → Record in Rekor

This works beautifully with GitHub Actions, GitLab CI 16.0+, and any CI system that provides OIDC tokens. The OIDC identity of the pipeline becomes the signing identity, creating a verifiable chain from source commit to signed image.

Pattern 2: Centralized Signing Service (Notation + KMS)

For enterprises that want separation of duties, a centralized signing service receives build artifacts and signs them using keys in a KMS:

Build Pipeline → Push to Registry → Request Signing → Notation Sign (KMS plugin) → Approval Workflow

This pattern enables scenarios where the build team cannot sign directly — a separate security team or automated policy engine must approve and sign the artifact. AWS Signer and Azure Key Vault access policies enforce who can request signatures.

Pattern 3: Verification Gates (Any Tool)

Regardless of which signing tool you use, the verification side is equally important. Implement verification at multiple points:

  • Pre-deployment gate: A Kubernetes admission controller (Kyverno, Gatekeeper + Ratify, Sigstore Policy Controller) rejects unsigned or incorrectly signed images.
  • Promotion gate: Before promoting an image from staging to production registry, verify its signature.
  • Runtime audit: Periodically scan running workloads and verify their signatures still hold against current trust policies.

Multi-Tool Strategy

Some organizations use multiple tools. For example, Cosign for CI/CD pipeline signing (keyless convenience) and Notation for release signing (enterprise PKI compliance). Both store signatures as OCI artifacts, so they can coexist on the same image. Verification policies can require signatures from both tools before allowing deployment.

The Future of Container Signing

The container signing landscape is converging on several important trends:

  • OCI 1.1 and the Referrers API: The OCI distribution spec now natively supports artifact references, which both Cosign and Notation leverage. This standardizes how signatures, SBOMs, and attestations attach to images.
  • SLSA and in-toto attestations: Signing is evolving beyond “who built this” to include verifiable build provenance, dependency manifests, and security scan results — all signed and attached to the image.
  • Policy-as-Code: Tools like Kyverno and Gatekeeper are making it possible to express complex signing requirements as declarative policies, reducing the gap between security intent and enforcement.
  • Sigstore adoption: Major package ecosystems (npm, PyPI, Maven Central) are adopting Sigstore, which increases familiarity and tooling maturity across the industry.

Conclusion and Recommendation

All three tools solve the fundamental problem of verifying container image authenticity, but they serve different contexts:

  • Cosign is the best choice for most teams. Keyless signing removes the operational burden that kills signing initiatives, the transparency log provides audit capabilities out of the box, and the ecosystem integration is the broadest. If you’re starting a new container signing initiative, start here.
  • Notation is the right choice for enterprises with established PKI and specific compliance requirements around key custody. Its plugin model and trust policy framework are designed for organizations that need fine-grained, delegated signing authority.
  • GPG should be reserved for legacy environments, fully air-gapped systems, or Podman-native workflows where the other tools genuinely can’t be used. For new deployments, the operational overhead of GPG key management is hard to justify.

The most important thing is to start signing. An imperfect signing implementation that actually ships is infinitely more valuable than a perfect one that stays on a roadmap. Pick the tool that matches your team’s capabilities, implement it in your pipeline, and add verification gates in Kubernetes. You can always evolve your tooling later — the critical step is establishing the practice.

Ready to get hands-on? Start with our Sigstore Keyless Signing Guide for the conceptual foundations, then work through the Cosign Keyless Signing Lab to implement it in a real GitHub Actions pipeline.