Support Sigstore bundle verification for cosign v3#3123
Support Sigstore bundle verification for cosign v3#3123SequeI wants to merge 2 commits intoconforma:mainfrom
Conversation
cosign v3 stores signatures as OCI referrer bundles by default, but ec only supported the legacy tag-based format. Detect bundles via cosign.GetBundles() and route verification through the bundle-aware code path, matching what the cosign CLI already does internally. Also fix typos and incorrect examples in CLI help text. Signed-off-by: SequeI <asiek@redhat.com>
Review Summary by QodoSupport Sigstore bundle verification for cosign v3
WalkthroughsDescription• Add support for Sigstore bundle verification for cosign v3 - Detect bundles via cosign.GetBundles() and route through bundle-aware code path - Implement ProvenanceFromBundlePayload() for parsing DSSE envelope payloads - Add parseAttestationsFromBundles() for extracting attestations from bundles • Fix CLI help text typos and incorrect command examples - Correct "form" to "from" in sigstore initialize help - Fix "expresssion" to "expression" typo in validate image help - Update example commands to use correct ec sigstore initialize syntax • Expose CreateRemoteOptions() as public function for bundle verification Diagramflowchart LR
A["Image with Bundles"] -->|hasBundles check| B["Bundle Path"]
A -->|no bundles| C["Legacy Tag Path"]
B -->|VerifyImageAttestations| D["parseAttestationsFromBundles"]
D -->|ProvenanceFromBundlePayload| E["Attestation Objects"]
C -->|VerifyImageSignatures| F["ProvenanceFromSignature"]
F --> E
File Changes1. cmd/sigstore/initialize.go
|
Code Review by Qodo
1. hasBundles() ignores GetBundles error
|
| func (a *ApplicationSnapshotImage) hasBundles(ctx context.Context) bool { | ||
| regOpts := []ociremote.Option{ociremote.WithRemoteOptions(oci.CreateRemoteOptions(ctx)...)} | ||
| bundles, _, err := cosign.GetBundles(ctx, a.reference, regOpts) | ||
| return err == nil && len(bundles) > 0 | ||
| } |
There was a problem hiding this comment.
1. hasbundles() ignores getbundles error 📘 Rule violation ⛯ Reliability
hasBundles() silently converts cosign.GetBundles() failures into false, which can route verification down the legacy path without surfacing the underlying failure. This can mask registry/network/auth problems and produce misleading verification behavior.
Agent Prompt
## Issue description
`hasBundles()` discards errors from `cosign.GetBundles()` and returns `false`, which can silently trigger the legacy verification path and hide real registry/network/auth failures.
## Issue Context
Bundle detection depends on an external call. Per compliance, failure points should be handled explicitly with actionable context (return error and/or log at an appropriate level).
## Fix Focus Areas
- internal/evaluation_target/application_snapshot_image/application_snapshot_image.go[125-171]
- internal/evaluation_target/application_snapshot_image/application_snapshot_image.go[192-206]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| if a.hasBundles(ctx) { | ||
| opts.NewBundleFormat = true | ||
| opts.ClaimVerifier = cosign.IntotoSubjectClaimVerifier | ||
| sigs, _, err = client.VerifyImageAttestations(a.reference, &opts) | ||
| } else { | ||
| opts.ClaimVerifier = cosign.SimpleClaimVerifier | ||
| sigs, _, err = client.VerifyImageSignatures(a.reference, &opts) |
There was a problem hiding this comment.
2. Signature check verifies attestations 🐞 Bug ⛨ Security
For bundle images, ValidateImageSignature verifies attestations (and uses the in-toto claim verifier) instead of verifying image signatures, so the ImageSignatureCheck can become semantically incorrect. This risks passing the “image signature” gate based on attestations rather than actual image signatures.
Agent Prompt
### Issue description
`ValidateImageSignature` switches to attestation verification for bundle images, which changes the meaning of the “image signature check” and can incorrectly pass it based on attestations.
### Issue Context
The system treats image signatures and attestation signatures as separate checks and documents them as distinct concepts.
### Fix Focus Areas
- internal/evaluation_target/application_snapshot_image/application_snapshot_image.go[154-171]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| // ProvenanceFromBundlePayload parses an attestation from a raw DSSE envelope | ||
| // JSON payload as returned by the Sigstore bundle verification path. | ||
| func ProvenanceFromBundlePayload(dsseJSON []byte) (Attestation, error) { | ||
| var payload cosign.AttestationPayload | ||
| if err := json.Unmarshal(dsseJSON, &payload); err != nil { | ||
| return nil, fmt.Errorf("malformed bundle attestation: %w", err) | ||
| } | ||
|
|
||
| if payload.PayLoad == "" { | ||
| return nil, errors.New("no `payload` data found in bundle attestation") | ||
| } | ||
|
|
||
| embedded, err := decodedPayload(payload) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| //nolint:staticcheck | ||
| var statement in_toto.Statement | ||
| if err := json.Unmarshal(embedded, &statement); err != nil { | ||
| return nil, fmt.Errorf("malformed bundle attestation: %w", err) | ||
| } | ||
|
|
||
| return provenance{statement: statement, data: embedded}, nil | ||
| } |
There was a problem hiding this comment.
3. Bundle attestations drop signatures 🐞 Bug ✓ Correctness
Bundle attestation parsing returns attestations without populating .Signatures(), so policy input .attestations[].signatures becomes empty/omitted for bundle format. This violates the documented policy-input contract and can break policies that expect attestation signatures to be present.
Agent Prompt
### Issue description
Bundle-derived attestations are added without `.signatures`, violating the documented policy-input schema and breaking policies that expect signature metadata.
### Issue Context
Legacy path uses `ProvenanceFromSignature` which calls `createEntitySignatures`. The bundle path parses a DSSE envelope but never populates `provenance.signatures`.
### Fix Focus Areas
- internal/attestation/attestation.go[146-170]
- internal/evaluation_target/application_snapshot_image/application_snapshot_image.go[251-281]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
cosign v3 stores signatures as OCI referrer bundles by default, but ec
only supported the legacy tag-based format. Detect bundles via
cosign.GetBundles() and route verification through the bundle-aware
code path, matching what the cosign CLI already does internally.
Also fix typos and incorrect examples in CLI help text.
You can check this behaviour out by using Cosign V3, signing an image, attaching the predicate.json, and trying to use
ec validatefrom main branch, then from this branch.