-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Summary
When a multi-arch (OCI index / manifest list) image is signed with cosign, the parent manifest list correctly shows the green checkmark in the "Signed" column, but all child platform images show a red X (unsigned) when viewed through the OCI index depth view.
This affects both scenarios:
- Signing the manifest list by tag (signature attached to the index)
- Signing a child image directly by digest
Steps to Reproduce
-
Push a multi-arch image to Harbor:
crane copy docker.io/library/alpine:latest localhost:8080/cosign-test/signed-image:alpine --insecure
-
Sign the manifest list with cosign:
cosign sign --key cosign.key --allow-insecure-registry --allow-http-registry \ localhost:8080/cosign-test/signed-image:alpine
-
Verify the signature:
cosign verify --key cosign.pub --allow-insecure-registry --allow-http-registry \ localhost:8080/cosign-test/signed-image:alpine # Verification succeeds -
Open the Harbor UI → Projects → cosign-test → signed-image → Artifacts tab
- The manifest list shows green checkmark in the Signed column ✅
-
Click the OCI index icon to drill into child platform images
- All child images show red X (unsigned) ❌
Expected Behavior
Child artifacts within a signed OCI index should either:
- Inherit the signed status from their parent manifest list, or
- At minimum, display an indicator that the parent index is signed
Actual Behavior
- Parent manifest list: Green checkmark (correct)
- Child images (linux/amd64, linux/arm64, etc.): Red X (misleading)
Parent manifest list — green checkmark
Child images in depth view — all red X
API Confirmation
The API confirms the signature accessory is only attached to the parent, not propagated to children:
# Parent — has cosign accessory
curl ".../artifacts/sha256:25109184...?with_accessory=true"
# → accessories: [{"type": "signature.cosign", ...}]
# Child — no accessories
curl ".../artifacts/sha256:1529d135...?with_accessory=true"
# → accessories: nullThis is technically correct (cosign signs exactly the digest it targets), but the UX is misleading since users expect the signed status to be visible on child images when the parent index is signed.
Customer Report Context
A customer on v2.13.2 reported this exact scenario: they signed an image, cosign verify succeeds, but the Harbor UI shows red X. Their cosign verify output confirmed the signature was on a specific child digest within a manifest list.
Related upstream issues (different root cause — cosign v3 bundle format):
- New cosign 2.6 signature format is not recognized by Harbor goharbor/harbor#22401
- cosign OCI referrers - Harbor sees the signature artifact as type: "UNKNOWN" instead of recognizing it as a cosign signature goharbor/harbor#22592
- Cosign does not work in 2.14.0 image is signed but 'signed' icon stay's red, debug proofs image is actually signed and well. goharbor/harbor#22643
- feat(cosign): Support Cosign v3 Bundle signature format goharbor/harbor#22628
Environment
- Harbor: latest main branch (post-v2.14.1)
- cosign: v3.0.4 (also reproduced with v2.2.4)
- Image: multi-arch
alpine:latest(all platforms)

