Skip to content

Cosign/Sigstore Reference: Sign Container Images, Keyless OIDC, SBOMs & K8s Policy Enforcement

Cosign (part of Sigstore) signs container images and other OCI artifacts, giving you cryptographic proof that an image was built by your pipeline and hasn’t been tampered with. It’s now the default signing tool in most supply chain security frameworks including SLSA, CNCF projects, and GitHub’s Artifact Attestations.

1. Cosign Concepts & Install

What Cosign signs, how signatures work, and install
Method Key storage Best for
Key-pair signing cosign.key / cosign.pub Simple, self-managed PKI
Keyless (OIDC) Fulcio CA + Rekor transparency log CI/CD — no key management
KMS-backed AWS KMS / GCP KMS / Vault Enterprise — HSM-backed keys
# Install:
brew install cosign                    # macOS
# Or: https://github.com/sigstore/cosign/releases (single binary)

# Keyless signing uses your OIDC identity (GitHub Actions, Google, etc.)
# No key to generate, store, or rotate
# Signature is anchored to your GitHub/Google identity + time via Fulcio + Rekor

# Key-pair signing (traditional):
cosign generate-key-pair                # creates cosign.key (encrypted) + cosign.pub
# Set COSIGN_PASSWORD env var to avoid interactive prompt in CI:
COSIGN_PASSWORD=my-pass cosign generate-key-pair

2. Sign & Verify Images

Sign after build, verify before deploy
# Sign with key-pair (after docker push):
cosign sign --key cosign.key ghcr.io/my-org/my-app:v1.2.3

# Sign with OIDC keyless (in CI — uses GitHub Actions OIDC token automatically):
cosign sign ghcr.io/my-org/my-app:v1.2.3
# No --key needed — Fulcio issues a short-lived cert tied to github.com/my-org/my-app

# Sign by digest (more stable than tag — tags can be rewritten):
IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' my-app:v1.2.3)
cosign sign --key cosign.key $IMAGE_DIGEST

# Verify with public key:
cosign verify --key cosign.pub ghcr.io/my-org/my-app:v1.2.3

# Verify keyless (check identity claims):
cosign verify   --certificate-identity-regexp "https://github.com/my-org/my-app/.github/workflows/.*"   --certificate-oidc-issuer https://token.actions.githubusercontent.com   ghcr.io/my-org/my-app:v1.2.3

# Verify output shows:
# [{"critical":{"identity":{"docker-reference":"ghcr.io/my-org/my-app"},...}}]
# If verification FAILS, cosign exits non-zero — use this in admission webhooks

3. GitHub Actions — Sign on Every Build

Full CI workflow: build, push, sign with keyless OIDC
# .github/workflows/build-sign.yml
name: Build, Push, Sign

on:
  push:
    branches: [main]
    tags: ['v*']

jobs:
  build-sign:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write              # REQUIRED for keyless OIDC signing

    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
          # Capture the digest for signing:
          outputs: type=image,push=true

      - name: Install cosign
        uses: sigstore/cosign-installer@v3

      - name: Sign image (keyless)
        run: |
          cosign sign --yes             ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
          # --yes skips interactive prompt in CI
          # Signature goes to Rekor public transparency log

      - name: Verify immediately
        run: |
          cosign verify             --certificate-identity-regexp "https://github.com/${{ github.repository }}/.github/workflows/.*"             --certificate-oidc-issuer https://token.actions.githubusercontent.com             ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

4. Attach & Verify SBOMs

Sign and attach Software Bill of Materials (SBOM) to images
# Generate SBOM with Syft:
brew install syft
syft ghcr.io/my-org/my-app:v1.2.3 -o cyclonedx-json > sbom.json

# Attach the SBOM to the image as an OCI attestation:
cosign attach sbom --sbom sbom.json ghcr.io/my-org/my-app:v1.2.3

# Or use attest (signs + attaches in one step):
cosign attest --predicate sbom.json   --type cyclonedx   --key cosign.key   ghcr.io/my-org/my-app:v1.2.3

# Verify the attestation:
cosign verify-attestation   --type cyclonedx   --key cosign.pub   ghcr.io/my-org/my-app:v1.2.3 | jq '.payload | @base64d | fromjson | .predicate'

# In-Toto provenance (SLSA):
cosign attest --predicate provenance.json   --type slsaprovenance   ghcr.io/my-org/my-app:v1.2.3

5. Policy Enforcement with Kyverno or Connaisseur

Enforce signature verification at admission time in Kubernetes
# Kyverno — require signed images in production namespace:
# (Kyverno 1.10+ has native Sigstore/Cosign support)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-signed-images
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-image-signature
      match:
        any:
          - resources:
              kinds: [Pod]
              namespaces: [production]
      verifyImages:
        - imageReferences:
            - "ghcr.io/my-org/*"    # match our images
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/my-org/*/.github/workflows/*"
                    issuer: "https://token.actions.githubusercontent.com"
                    rekor:
                      url: https://rekor.sigstore.dev

# Any pod in 'production' that uses an unsigned image from ghcr.io/my-org/
# will be rejected by the admission webhook.

# Quick manual enforcement (admission not set up yet):
# Verify in your deployment pipeline before kubectl apply:
cosign verify --key cosign.pub $IMAGE_REF || { echo "Image unsigned, aborting"; exit 1; }
kubectl apply -f deployment.yaml

Track Cosign, Sigstore, and supply chain security tool releases.
ReleaseRun monitors Kubernetes, Docker, and 13+ DevOps technologies.

Related: Trivy Reference | Kyverno Reference | GitHub Actions Reference

🔍 Free tool: K8s YAML Security Linter — complement cosign image signing by also checking your K8s manifests for 12 security misconfigurations.

Founded

2023 in London, UK

Contact

hello@releaserun.com