CVE-2022-35929 (Go, published 2022-08-04T19:15Z)
Description: value: cosign is a container signing and verification utility. In versions prior to 1.10.1 cosign can report a false positive if any attestation exists. `cosign verify-attestation` used with the `--type` flag will report a false positive verification when there is at least one attestation with a valid signature and there are NO attestations of the type being verified (--type defaults to "custom"). This can happen when signing with a standard keypair and with "keyless" signing with Fulcio. This vulnerability can be reproduced with the `distroless.dev/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2` image. This image has a `vuln` attestation but not an `spdx` attestation. However, if you run `cosign verify-attestation --type=spdx` on this image, it incorrectly succeeds. This issue has been addressed in version 1.10.1 of cosign. Users are advised to upgrade. There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-347 \u2014 Improper Verification of Cryptographic Signature
The product does not verify, or incorrectly verifies, the cryptographic signature for data.
Repository: https://github.com/sigstore/cosign
Files changed:
cmd/cosign/cli/verify/verify_attestation.go
Commit message: Merge pull request from GHSA-vjxv-45g9-9296

Today the verification logic:
1. Verifies signatures on attestations (at least one must verify, or it errors),
2. All attestations matching the specified `--type` must pass any specified Cue/Rego policies,
3. *All* signature-verified attestations are then printed.

However, if NONE of the attestations match the specified `--type` then `2.` is considered satisfied and we proceed to `3.`

This changes the above logic to:
1. Same.
2. Same, but these are put into a `checked` list,
3. `checked` must be non-empty (or an error is printed about no attestations matching `--type`),
4. *Just* the `checked` attestations are printed.

---

The bug at HEAD:
```shell
$ cosign verify-attestation --type spdx ghcr.io/distroless/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2

Verification for ghcr.io/distroless/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - Any certificates were verified against the Fulcio roots.
Certificate subject:  https://github.com/distroless/static/.github/workflows/release.yaml@refs/heads/main
Certificate issuer URL:  https://token.actions.githubusercontent.com
Certificate extension GitHub Workflow Trigger: schedule
Certificate extension GitHub Workflow SHA: 7e7572e578de7c51a2f1a1791f025cf315503aa2
Certificate extension GitHub Workflow Name: Create Release
Certificate extension GitHub Workflow Trigger distroless/static
Certificate extension GitHub Workflow Ref: refs/heads/main
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjb3NpZ24uc2lnc3RvcmUuZGV2L2F0dGVzdGF0aW9uL3Z1bG4vdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiZ2hjci5pby9kaXN0cm9sZXNzL3N0YXRpYyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJkZDc2MTRiNWExMmJjNGQ2MTdiMjIzYzU4OGI0ZTBjODMzNDAyYjhmNDk5MWZiNTcwMmVhODNhZmFkMTk4NmUyIn19XSwicHJlZGljYXRlIjp7Imludm9jYXRpb24iOnsicGFyYW1ldGVycyI6bnVsbCwidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2Rpc3Ryb2xlc3Mvc3RhdGljL2FjdGlvbnMvcnVucy8yNzc5MjEyNzA1IiwiZXZlbnRfaWQiOiIyNzc5MjEyNzA1IiwiYnVpbGRlci5pZCI6IkNyZWF0ZSBSZWxlYXNlIn0sInNjYW5uZXIiOnsidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2FxdWFzZWN1cml0eS90cml2eSIsInZlcnNpb24iOiIwLjI5LjIiLCJkYiI6eyJ1cmkiOiIiLCJ2ZXJzaW9uIjoiIn0sInJlc3VsdCI6eyIkc2NoZW1hIjoiaHR0cHM6Ly9qc29uLnNjaGVtYXN0b3JlLm9yZy9zYXJpZi0yLjEuMC1ydG0uNS5qc29uIiwicnVucyI6W3siY29sdW1uS2luZCI6InV0ZjE2Q29kZVVuaXRzIiwib3JpZ2luYWxVcmlCYXNlSWRzIjp7IlJPT1RQQVRIIjp7InVyaSI6ImZpbGU6Ly8vIn19LCJyZXN1bHRzIjpbXSwidG9vbCI6eyJkcml2ZXIiOnsiZnVsbE5hbWUiOiJUcml2eSBWdWxuZXJhYmlsaXR5IFNjYW5uZXIiLCJpbmZvcm1hdGlvblVyaSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9hcXVhc2VjdXJpdHkvdHJpdnkiLCJuYW1lIjoiVHJpdnkiLCJydWxlcyI6W10sInZlcnNpb24iOiIwLjI5LjIifX19XSwidmVyc2lvbiI6IjIuMS4wIn19LCJtZXRhZGF0YSI6eyJzY2FuU3RhcnRlZE9uIjoiMjAyMi0wOC0wMlQwMjozMzo0N1oiLCJzY2FuRmluaXNoZWRPbiI6IjIwMjItMDgtMDJUMDI6MzM6NTNaIn19fQ==","signatures":[{"keyid":"","sig":"MEYCIQCovBtLOBXyB2zpvhp3j6QzqLtsH0/RC7fRINSApySqxAIhAIKlzu1fXuKPPOIheNnsPmBOB6XfZbRs5sDW1yFSch1A"}]}
```

The same with this change:
```shell
$ go run ./cmd/cosign verify-attestation --type spdx ghcr.io/distroless/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2
Error: none of the attestations matched the predicate type: spdx
main.go:62: error during command execution: none of the attestations matched the predicate type: spdx
exit status 1
```

A valid `--type` with this change:
```shell
$ go run ./cmd/cosign verify-attestation --type vuln ghcr.io/distroless/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2

Verification for ghcr.io/distroless/static@sha256:dd7614b5a12bc4d617b223c588b4e0c833402b8f4991fb5702ea83afad1986e2 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - Any certificates were verified against the Fulcio roots.
Certificate subject:  https://github.com/distroless/static/.github/workflows/release.yaml@refs/heads/main
Certificate issuer URL:  https://token.actions.githubusercontent.com
Certificate extension GitHub Workflow Trigger: schedule
Certificate extension GitHub Workflow SHA: 7e7572e578de7c51a2f1a1791f025cf315503aa2
Certificate extension GitHub Workflow Name: Create Release
Certificate extension GitHub Workflow Trigger distroless/static
Certificate extension GitHub Workflow Ref: refs/heads/main
{"payloadType":"application/vnd.in-toto+json","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjb3NpZ24uc2lnc3RvcmUuZGV2L2F0dGVzdGF0aW9uL3Z1bG4vdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiZ2hjci5pby9kaXN0cm9sZXNzL3N0YXRpYyIsImRpZ2VzdCI6eyJzaGEyNTYiOiJkZDc2MTRiNWExMmJjNGQ2MTdiMjIzYzU4OGI0ZTBjODMzNDAyYjhmNDk5MWZiNTcwMmVhODNhZmFkMTk4NmUyIn19XSwicHJlZGljYXRlIjp7Imludm9jYXRpb24iOnsicGFyYW1ldGVycyI6bnVsbCwidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2Rpc3Ryb2xlc3Mvc3RhdGljL2FjdGlvbnMvcnVucy8yNzc5MjEyNzA1IiwiZXZlbnRfaWQiOiIyNzc5MjEyNzA1IiwiYnVpbGRlci5pZCI6IkNyZWF0ZSBSZWxlYXNlIn0sInNjYW5uZXIiOnsidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2FxdWFzZWN1cml0eS90cml2eSIsInZlcnNpb24iOiIwLjI5LjIiLCJkYiI6eyJ1cmkiOiIiLCJ2ZXJzaW9uIjoiIn0sInJlc3VsdCI6eyIkc2NoZW1hIjoiaHR0cHM6Ly9qc29uLnNjaGVtYXN0b3JlLm9yZy9zYXJpZi0yLjEuMC1ydG0uNS5qc29uIiwicnVucyI6W3siY29sdW1uS2luZCI6InV0ZjE2Q29kZVVuaXRzIiwib3JpZ2luYWxVcmlCYXNlSWRzIjp7IlJPT1RQQVRIIjp7InVyaSI6ImZpbGU6Ly8vIn19LCJyZXN1bHRzIjpbXSwidG9vbCI6eyJkcml2ZXIiOnsiZnVsbE5hbWUiOiJUcml2eSBWdWxuZXJhYmlsaXR5IFNjYW5uZXIiLCJpbmZvcm1hdGlvblVyaSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9hcXVhc2VjdXJpdHkvdHJpdnkiLCJuYW1lIjoiVHJpdnkiLCJydWxlcyI6W10sInZlcnNpb24iOiIwLjI5LjIifX19XSwidmVyc2lvbiI6IjIuMS4wIn19LCJtZXRhZGF0YSI6eyJzY2FuU3RhcnRlZE9uIjoiMjAyMi0wOC0wMlQwMjozMzo0N1oiLCJzY2FuRmluaXNoZWRPbiI6IjIwMjItMDgtMDJUMDI6MzM6NTNaIn19fQ==","signatures":[{"keyid":"","sig":"MEYCIQCovBtLOBXyB2zpvhp3j6QzqLtsH0/RC7fRINSApySqxAIhAIKlzu1fXuKPPOIheNnsPmBOB6XfZbRs5sDW1yFSch1A"}]}
```

Signed-off-by: Matt Moore <mattmoor@chainguard.dev>

Vulnerable code:
		PrintVerification(imageRef, verified, "text")

Fixed code:
		var checked []oci.Signature
					continue
					continue

			checked = append(checked, vp)
		if len(checked) == 0 {
			return fmt.Errorf("none of the attestations matched the predicate type: %s", c.PredicateType)
		}

		PrintVerification(imageRef, checked, "text")