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: writeandpackages: 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
How to Scan a Docker Image With Trivy and Fail on HIGH in CIScan a built Docker image with Aqua Trivy in CI and fail the job when HIGH or CRITICAL vulnerabilities are fo…
How to Attest Docker Build Provenance in CIGenerate a signed SLSA provenance attestation for a pushed Docker image in CI with the attest-build-provenanc…