## TL;DR
No matching signatures means cosign found the signature artifact but none of the signatures validate against the key or identity you told it to trust. Verify what the image was actually signed with, then align the verification key, the expected identity, or the signature lookup.

```text
Error: no matching signatures
```

## Steps

1. Inspect what signatures exist for the image:
```bash
cosign triangulate [IMAGE]:[TAG]
```
Expected: the signature artifact reference cosign is checking, confirming it is looking in the right place.

2. Verify with verbose output to see why each signature was rejected:
```bash
cosign verify --key [KEY_PATH] [IMAGE]:[TAG] --verbose
```
Expected: per-signature rejection reasons, such as key mismatch or certificate identity mismatch, instead of the bare error.

3. Check whether the image was signed with a different key than you are verifying with:
```bash
cosign verify --key [KEY_PATH] [IMAGE]:[TAG] | head -5
```
Expected: either success or a clear key mismatch. If the signing key rotated, update the verification key to the current public key.

4. For keyless signing, verify the expected identity matches the signer:
```bash
cosign verify [IMAGE]:[TAG] \
  --certificate-identity "[EXPECTED_IDENTITY]" \
  --certificate-oidc-issuer "[EXPECTED_ISSUER]"
```
Expected: success when the identity and issuer match what the signing workflow used. A workflow moved to a new repo or ref changes the identity.

5. Confirm the digest you verify is the digest that was signed:
```bash
docker inspect [IMAGE]:[TAG] --format '{{.RepoDigests}}'
```
Expected: the digest matches the one in the signing job's output. Verifying a rebuilt or retagged image against the old image's signatures always fails.

## When to use
- cosign verify fails in CI with no matching signatures on an image you signed
- Verification broke after a key rotation or a workflow move
- Keyless verification fails after renaming the repo or changing the branch

## When not to use
- The error is about a missing signature artifact; that is a signing step that never ran
- cosign cannot reach the registry; that is network or auth, not signatures
- You have not set up signing yet; this skill is for debugging verification, not bootstrapping it

## Why it happens
Signatures bind to the exact image digest, the signing key, and (for keyless) the OIDC identity of the signer. Any drift, a rotated key, a rebuilt image with a new digest, a workflow renamed so its identity changed, breaks the match. Cosign reports all of these as the same terse error.

## Edge cases
- Multi-arch images need verification per digest or against the index; verifying one platform's digest against another's signature fails
- Some registries strip or relocate signature artifacts on copy; copy signatures explicitly when promoting images between registries
- Expired Fulcio certificates still verify if the timestamp is valid; do not assume expiry is the cause without the verbose output
- A `--key` pointing at the private key instead of the public key fails confusingly; verify with the .pub file

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_LWJIkX5A3coyaYzlSibf4g
