How to Use Cosign: The Beginner's Guide to Signing Container Images
CodexFuse Team · 2026-10-31T17:02:12.000Z · 13 min read min read
Install Cosign, generate your first key pair, sign your first image by digest, verify the signature, and go keyless with Sigstore's OIDC flow.
Cosign — the container-image signing tool from the Sigstore project, not the medical co-signing paperwork — answers one question about every image you ship: did this exact image come from someone I trust, unmodified? Learning how to use Cosign means learning to attach a cryptographic signature to an image and then check that signature before you run or deploy it. This cosign tutorial is the beginner arc the field has been missing: install, your first key pair, your first signature on a real image digest, verification, the keyless OIDC flow, and your first SBOM attestation — all in one guide, current for Cosign v3. It assumes you know images from our Docker beginner guide, because Cosign signs the images Docker builds.
What is Cosign, exactly?
Cosign is a command-line tool from the open-source Sigstore project (Apache-2.0 license) that signs container images and other software artifacts, then lets anyone verify those signatures before running the software. Signing proves provenance: the signature says this exact image was built and approved by this identity, and verification confirms the image has not changed by a single byte since. It stores signatures right next to the image in your registry — v3 uses the OCI 1.1 referrers API by default and can also write a portable Sigstore bundle file — and it needs no signing infrastructure of your own, because keyless mode leans on Sigstore's public Fulcio certificate authority and Rekor transparency log. As of this writing, the project (sigstore/cosign on GitHub) sits at roughly 6,400 stars with v3.1.4 released on October 20, 2026 — install the newest release, because the v3 bundle format is the current default and older guides still describe v1 behavior.
How do I install Cosign?
Install Cosign through whatever channel fits your machine — the fastest path is your package manager, and the official docs keep the full list current. This cosign install arc assumes a Linux or macOS machine with Docker installed.
# macOS (official docs path)
brew install cosign
# Arch
pacman -S cosign
# Alpine
apk add cosign
# Nix
nix-env -iA nixpkgs.cosign
# Go toolchain (works anywhere)
go install github.com/sigstore/cosign/v3/cmd/cosign@latest
# GitHub Actions (official installer)
# uses: sigstore/[email protected]
Check the version after installing with cosign version — if it reports v3.x, every command in this guide works as written. Cosign for beginners tip: avoid copying commands from the December 2021 opensource.com overview or any v1-era blog post, because key generation and the signature storage format both changed across versions.
How do I generate my first Cosign key pair?
Run cosign generate-key-pair — it prompts you for a password, then writes two files into your current directory: cosign.key (your private key, password-encrypted) and cosign.pub (your public key, safe to share). Cosign supports RSA, ECDSA, and ED25519 keys, and if your org keeps keys in a vault or cloud KMS instead of files, the same command takes a KMS reference: cosign generate-key-pair --kms awskms:///alias/my-key.
# Set the key password non-interactively (handy for scripts)
export COSIGN_PASSWORD="a-long-random-password"
cosign generate-key-pair
# Enter password for private key: ...
# Re-enter password for private key: ...
# Private key written to cosign.key
# Public key written to cosign.pub
Now the security lesson that makes the whole tool trustworthy: cosign.key is a secret — keep it off Git, out of chat, and out of your CI logs. The cosign generate key pair step leaves you holding the entire identity, so treat the private half like a password: the key file is encrypted at rest (scrypt KDF with nacl/secretbox, visible as an ENCRYPTED COSIGN PRIVATE KEY PEM header), but encryption is a seatbelt, not a vault — never commit the file to a repo. A current community guide puts it bluntly — "The private key. Keep this secret. Never commit it to Git." If your key ever leaks, signatures it made are still valid, so rotate to a new key pair and re-sign.
How do I sign a container image with Cosign?
Sign the image digest, never the tag: a tag like myapp:latest can be repointed at a different image tomorrow, while a digest like myapp@sha256:9f3c... names one immutable image forever. Cosign signs the exact digest and refuses to verify a mismatched one, so the digest rule is the load-bearing lesson of this whole guide. Here is the 7-step first-signature arc:
- Build and push an image to a registry you control. A throwaway test image on Docker Hub or a local registry is perfect for practice.
- Read back the image's digest. The push output prints it, or ask the registry:
docker buildx imagetools inspect myuser/myapp:latest --format '{{json .Manifest}}'is one reliable way. - Point a variable at the digest, not the tag.
IMAGE=myuser/myapp@sha256:9f3c2b...— every command below uses$IMAGE. - Sign it.
cosign sign --key cosign.key $IMAGE— Cosign uploads the signature to the registry alongside the image. - Attach annotations if you want metadata.
cosign sign -a ci=github-actions -a commit=abc123 --key cosign.key $IMAGEstamps context into the signature. - Confirm where the signature landed.
cosign tree $IMAGEshows the image, its signature, and any attestations as a tree. - Double-check that cosign.key is git-ignored. Run
git status— if cosign.key shows up, add it to.gitignoreright now.
| What you sign | What happens when the tag moves | Verdict |
|---|---|---|
The tag (myapp:latest) | The signature stays glued to whatever the tag points at today — an attacker who repoints the tag inherits your signature | Never do this |
The digest (myapp@sha256:...) | The signature is bound to one immutable image; a repointed tag simply fails verification | Always do this |
| Digest + annotations | Same binding, plus searchable build metadata inside the signature | The professional habit |
That table is the whole reason this container image signing tutorial exists: every real-world Cosign failure story starts with someone signing a tag. Make the digest a reflex and the rest is mechanical — every cosign sign image command in this guide uses the digest form, because you sign container image digests with Cosign, never tags.
How do I verify a Cosign signature?
Verification is one command: cosign verify --key cosign.pub $IMAGE. Give it the public key and the digest-addressed image, and it answers three questions at once — is the signature cryptographically valid, does the signed digest match the image you handed it, and was it made by the holder of this key? A clean run prints a JSON list of the verified signatures; a tampered image or wrong key exits non-zero, which is exactly what makes it usable as a CI gate. The public key can also be fetched from a URL (cosign verify --key https://myorg.example.com/cosign.pub $IMAGE), which is how teams publish their signing key without shipping files around.
# Verify with a local public key
cosign verify --key cosign.pub $IMAGE
# Verify with a published public key
cosign verify --key https://myorg.example.com/cosign.pub $IMAGE
# See signatures and attestations attached to the image
cosign tree $IMAGE
To sign a container image and then verify it is the complete beginner loop — everything after this point is automation and scale. Practice the loop until cosign sign followed by cosign verify feels boring; boring is the goal, because boring means your supply chain is under control.
What is keyless signing in Sigstore Cosign?
Keyless signing replaces your long-lived private key with a short-lived certificate tied to your identity: you authenticate through an OIDC provider (Google, GitHub, or Microsoft in the browser flow), Sigstore's Fulcio certificate authority issues a certificate valid for minutes, and the signature plus its certificate go into the public Rekor transparency log. With the cosign keyless flow, nothing secret lives on your laptop or in your CI — there is no cosign.key to leak, rotate, or lose. The whole flow is two commands:
# Sign keylessly (opens a browser for OIDC auth; --yes skips the prompt in CI)
cosign sign --yes $IMAGE
# Verify a keyless signature: check WHO signed, not just THAT it is signed
cosign verify $IMAGE \
[email protected] \
--certificate-oidc-issuer=https://github.com/login/oauth
The verify command is where beginners stumble: --certificate-identity must match the exact identity that signed (for GitHub Actions, that is the workflow's identity string), and --certificate-oidc-issuer must match the issuer that authenticated it. Checking identity-plus-issuer is the difference between "someone signed this" and "my CI pipeline signed this" — always verify the identity, never just the signature's existence.
| Sigstore piece | What it does | Production endpoint |
|---|---|---|
| Fulcio | Issues short-lived certificates from your OIDC identity | https://fulcio.sigstore.dev |
| Rekor | Append-only transparency log of every signature | https://rekor.sigstore.dev |
| OIDC | Identity provider handshake (Google, GitHub, Microsoft) | https://oauth2.sigstore.dev/auth |
| TSA | Trusted timestamping for signatures | https://timestamp.sigstore.dev |
| TUF | Secure distribution of Sigstore's root keys | https://tuf-repo-cdn.sigstore.dev |
Keyless or key pair: which should a beginner choose?
Choose keyless for CI and key pairs for offline or air-gapped work — the decision takes thirty seconds and saves hours of rework. Both modes verify with the same cosign verify grammar, so you are not locked in.
| Factor | Keyless (OIDC) | Key pair (cosign.key) |
|---|---|---|
| Secrets to manage | None — identity comes from your OIDC provider | The private key file and its password |
| Works offline / air-gapped | No — needs Fulcio, Rekor, and the OIDC provider | Yes — fully local |
| CI fit | Excellent — GitHub Actions OIDC, no stored secrets | Workable — key must be injected as a secret |
| Identity model | Who you are (email / workflow identity) | Whoever holds the key |
| Biggest beginner risk | Verifying without checking certificate identity | Committing cosign.key to the repo |
Most teams land on the same split: keyless in CI where OIDC is available, a password-protected key pair for the release laptop and the air-gapped registry. Learn both on your practice image so the choice is deliberate, not accidental.
How do I attest an SBOM with Cosign?
An attestation is a signature on a statement about the image rather than on the image itself — the classic statement is an SBOM (software bill of materials) listing everything inside the image. Signing says "this image is authentic"; attesting an SBOM says "and here is exactly what it contains, also authentic." Generate the SBOM first (Syft is the usual tool), then attest:
# Attest an SBOM predicate to the image
cosign attest --predicate sbom.spdx.json --key cosign.key $IMAGE
# Verify the attestation (keyless adds the certificate flags)
cosign verify-attestation --key cosign.pub \
--type spdxjson $IMAGE
One honest caveat from the official docs: the whole SBOM gets bundled into the attestation, and verification downloads the entire bundle again — for large images that is slow and heavy. If your SBOM is huge, attest a digest of it or reference it from a predicate instead of embedding the full document. Either way, this cosign sbom attestation flow is the bridge from "signed" to "signed and auditable," and auditors love it.
Can I use Cosign with Kubernetes?
Yes — and this is where signing pays off: instead of verifying images by hand, you verify them at deploy time with an admission controller that refuses to run unsigned images. The three common enforcers are Kyverno (a policy engine with Cosign verification rules), Connaisseur (a dedicated image-verification admission controller), and Sigstore's own policy-controller. The pattern is always the same: the controller intercepts each pod creation, runs the equivalent of cosign verify against the image's signature, and admits or rejects the pod before a single container starts. It is the natural capstone after the K3s beginner guide — you built the cluster, now you decide which images are allowed inside it. This cosign kubernetes lane is also why signing the digest matters twice over: admission policies match digests, never tags.
How do Cosign, Trivy, and Falco fit together?
Beginners often ask whether signing replaces scanning — it does not. The three tools cover three different questions about your containers, and the secure-supply-chain stack runs all of them in order. If you have not scanned yet, start with our Trivy beginner guide; if you want runtime eyes on the cluster afterward, the Falco beginner guide is the next stop.
| Question | Tool | When it runs | What it proves |
|---|---|---|---|
| "Is anything inside this image vulnerable?" | Trivy | Before you sign — scan the image | The image has no known critical flaws (at scan time) |
| "Did this exact image come from my pipeline, unmodified?" | Cosign | After the scan passes — sign the digest | Provenance and integrity of the image |
| "Is the running container behaving itself?" | Falco | After deploy — watch the runtime | No suspicious behavior at runtime |
The one-line version: Trivy finds flaws, Cosign proves provenance, Falco catches misbehavior. Scan, then sign, then watch — skip any step and you have a blind spot with your name on it.
What are the 7 beginner mistakes with Cosign?
Every one of these comes from a real support thread or tutorial comment — read the table once and you will skip the week of confusion most beginners pay.
| Mistake | Why it hurts | The fix |
|---|---|---|
| Signing the tag instead of the digest | Tags move — your signature quietly follows whatever the tag points at | Always IMAGE=repo@sha256:... before any sign or verify |
| Committing cosign.key to the repo | Anyone with the key can sign as you, forever | .gitignore it on day one; prefer keyless in CI |
| Verifying without checking the identity | "Signed" tells you nothing about who signed | Always pass --certificate-identity and --certificate-oidc-issuer for keyless |
| Following v1-era commands | Key generation, storage format, and defaults all changed in v2/v3 | Match your commands to your installed version (v3.1.4 at writing) |
| Expecting signatures to survive a registry mirror | Some mirrors strip referrers/attachments — signatures live in the registry | Verify against the registry you signed in, or ship the bundle file |
| Attesting a 50 MB SBOM into every image | Verification downloads the whole bundle every time | Attest a digest/reference for huge SBOMs; embed only small ones |
| Skipping the scan before the signature | A signed vulnerable image is still a vulnerable image | Trivy scan first, sign second — provenance is not a security patch |
Sources
Facts in this guide were verified at write time (October 31, 2026) from: the GitHub sigstore/cosign releases API (v3.1.4 released October 20, 2026; ~6,400 stars; Apache-2.0); docs.sigstore.dev — installation, signing with containers, verifying, other types (attestations), and key management with self-managed keys; Sigstore's own prober workflow defaults for the production Fulcio/Rekor/OIDC/TSA/TUF endpoints; the perlod.com Cosign-plus-Kyverno guide (updated ~49 days ago); the opensource.com Sigstore overview (December 2021, v1-era); the devopscube container-image-signing-for-Kubernetes guide (~55 days ago); the witalis.net keyless-plus-GitHub-OIDC walkthrough; and the glen-thomas.com Cosign-vs-Notation walkthrough (January 2026).
Frequently Asked Questions
Is Cosign free to use?
Yes. Cosign is open source under the Apache-2.0 license, and keyless signing uses Sigstore's free public infrastructure (Fulcio, Rekor, and the OIDC service) — there is no account, no bill, and no API key for the standard flow.
Do I need a private key to use Cosign?
No. Keyless mode authenticates you through an OIDC provider and issues a short-lived certificate, so there is no long-lived private key to create, protect, or rotate. Key pairs are still the right choice for offline or air-gapped environments where Sigstore's public services are unreachable.
What is the difference between cosign sign and cosign attest?
cosign sign signs the image itself — it vouches for the image's integrity and provenance. cosign attest signs a statement about the image, such as an SBOM or a build provenance document — it vouches for claims attached to the image. Verify attestations with cosign verify-attestation.
Can Cosign sign things other than container images?
Yes. Cosign signs arbitrary blobs (cosign sign-blob) and WASM modules too, and the same verify/attest grammar applies. This guide focuses on images because that is where beginners meet it first.
Why did my cosign verify fail with "no matching signatures"?
The usual causes, in order: you verified the tag instead of the digest you signed, you pointed at the wrong public key, the image was rebuilt (new digest — signatures do not transfer), or for keyless, the certificate identity or OIDC issuer flags do not match the signer. Re-run with the exact digest and matching key or identity flags.