Skip to content
Latchkey

How to Sign a Docker Image With Cosign Keyless in CI

Keyless cosign signs an image using a short-lived OIDC identity and records the signature in a transparency log, with no key to manage.

Grant id-token: write, install cosign with sigstore/cosign-installer, push the image by digest, then run cosign sign with COSIGN_EXPERIMENTAL=1. The signature is tied to the workflow identity via Fulcio and logged in Rekor.

Steps

  • Add permissions: id-token: write and packages: write.
  • Install cosign with sigstore/cosign-installer.
  • Capture the pushed image digest and run cosign sign --yes <ref>@<digest>.

Workflow

.github/workflows/docker.yml
permissions:
  id-token: write
  packages: write
  contents: read
jobs:
  sign:
    runs-on: ubuntu-latest
    steps:
      - uses: sigstore/cosign-installer@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: push
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:latest
      - run: cosign sign --yes ghcr.io/${{ github.repository }}@${{ steps.push.outputs.digest }}

Gotchas

  • Sign by digest, not a mutable tag, so the signature always refers to the exact image you built.
  • Verify later with cosign verify --certificate-identity-regexp ... --certificate-oidc-issuer https://token.actions.githubusercontent.com.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →