Skip to content

Commit dcdb82c

Browse files
committed
feat: add documentation for working with OCI 1.0 and OCI 1.1 container registries
Signed-off-by: Kevin Conner <kev.conner@gmail.com>
1 parent b5c91a0 commit dcdb82c

File tree

4 files changed

+507
-4
lines changed

4 files changed

+507
-4
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
type: docs
3+
title: "Container Registries"
4+
description: "Documentation for working with container registries"
5+
lead: ""
6+
date: 2020-10-06T08:49:15+00:00
7+
lastmod: 2020-10-06T08:49:15+00:00
8+
draft: false
9+
images: []
10+
weight: 80
11+
---
12+
13+
14+
Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
---
2+
type: docs
3+
category: Container Registries
4+
title: OCI and Referrers
5+
weight: 750
6+
---
7+
8+
Cosign supports the OCI 1.1 specification, which introduces the **referrers API** for discovering artifacts associated with a container image. This page explains how cosign uses the referrers API and how to configure signature and attestation storage modes.
9+
10+
## Who Is This For?
11+
12+
This page is for:
13+
14+
- **Anyone migrating from cosign 2.x to 3.0+**, where the new bundle format and OCI 1.1 referrers API become the default behavior
15+
- **Image producers** who want to understand how cosign stores signatures and attestations, and which mode is appropriate for their registry
16+
- **Tooling authors and operators** who need to discover and inspect cosign artifacts using standard OCI tools like `oras`, independent of cosign itself
17+
- **Anyone troubleshooting** why cosign signatures are not being found or verified, as different storage modes produce artifacts in different locations that require different discovery approaches
18+
19+
## What is the Referrers API?
20+
21+
The OCI Distribution Specification 1.1 introduced the referrers API as a standardized way to discover artifacts (like signatures, attestations, and SBOMs) associated with a container image.
22+
23+
Instead of relying on tag naming conventions (e.g., `sha256-<digest>.sig`), the referrers API uses a `subject` field in the artifact manifest to create a direct relationship between the artifact and the image it references. Registries that support OCI 1.1 expose a `/referrers/<digest>` endpoint that returns all artifacts linked to a given image digest.
24+
25+
## Valid Format and Storage Combinations
26+
27+
| Bundle Format | Storage Mode | Signatures | Attestations | Notes |
28+
|--------------|--------------|------------|--------------|-------|
29+
| New (`--new-bundle-format=true`) | Referrers (OCI 1.1) | Yes | Yes | **Default in cosign 3.0+** |
30+
| New (`--new-bundle-format=true`) | Tag-based (OCI 1.0) | Yes | Yes | Uses referrers tag fallback (`sha256-<digest>`) |
31+
| Old (`--new-bundle-format=false`) | Referrers (OCI 1.1) | Yes | No | Signatures only; attestations always use tags |
32+
| Old (`--new-bundle-format=false`) | Tag-based (OCI 1.0) | Yes | Yes | Legacy mode |
33+
34+
### Key Constraints
35+
36+
1. **Old format requires disabling signing config**: When using `--new-bundle-format=false`, you must also set `--use-signing-config=false`. The default TUF-based signing config requires the new bundle format.
37+
38+
2. **Old format attestations always use tags**: When using `--new-bundle-format=false`, attestations are always stored using tag-based storage, regardless of any `--registry-referrers-mode` flag.
39+
40+
## Bundle Format: New vs Old
41+
42+
The `--new-bundle-format` flag controls the internal structure of the artifact cosign pushes to the registry. This is distinct from *where* it is stored (referrers API vs tag-based).
43+
44+
### New bundle format (default in cosign 3.0+)
45+
46+
Both signatures and attestations use an `artifactType` of `application/vnd.dev.sigstore.bundle.v0.3+json`, and the manifest contains a single layer that is a self-contained [sigstore bundle](https://github.com/sigstore/protobuf-specs). This bundle contains a DSSE envelope holding the signature or attestation, and all the verification material needed for offline verification.
47+
48+
```json
49+
{
50+
"schemaVersion": 2,
51+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
52+
"artifactType": "application/vnd.dev.sigstore.bundle.v0.3+json",
53+
"config": {
54+
"mediaType": "application/vnd.oci.empty.v1+json",
55+
"size": 2,
56+
"digest": "sha256:44136f..."
57+
},
58+
"layers": [
59+
{
60+
"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
61+
"size": 4262,
62+
"digest": "sha256:ab6e3f..."
63+
}
64+
],
65+
"annotations": {
66+
"dev.sigstore.bundle.content": "dsse-envelope",
67+
"dev.sigstore.bundle.predicateType": "https://sigstore.dev/cosign/sign/v1",
68+
"org.opencontainers.image.created": "2026-03-16T17:31:24Z"
69+
},
70+
"subject": {
71+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
72+
"size": 1022,
73+
"digest": "sha256:59855d..."
74+
}
75+
}
76+
```
77+
78+
See [Discovering Referrers](#discovering-referrers) for how to inspect these with `oras`.
79+
80+
### Old bundle format (`--new-bundle-format=false`)
81+
82+
**Signatures** use a config `mediaType` of `application/vnd.oci.image.config.v1+json` with layers of type `application/vnd.dev.cosign.simplesigning.v1+json`. The layer descriptor carries the cryptographic signature in the `dev.cosignproject.cosign/signature` annotation and the Rekor transparency log entry in `dev.sigstore.cosign/bundle`. Each signing event appends a new layer.
83+
84+
```json
85+
{
86+
"schemaVersion": 2,
87+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
88+
"config": {
89+
"mediaType": "application/vnd.oci.image.config.v1+json",
90+
"size": 233,
91+
"digest": "sha256:806ede..."
92+
},
93+
"layers": [
94+
{
95+
"mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
96+
"size": 242,
97+
"digest": "sha256:c7875f...",
98+
"annotations": {
99+
"dev.cosignproject.cosign/signature": "MEUC...",
100+
"dev.sigstore.cosign/bundle": "{...}"
101+
}
102+
}
103+
]
104+
}
105+
```
106+
107+
When stored via the OCI 1.1 referrers API, the config `mediaType` is `application/vnd.dev.cosign.artifact.sig.v1+json` and a `subject` field is added linking the artifact to the signed image.
108+
109+
**Attestations** use a config `mediaType` of `application/vnd.oci.image.config.v1+json` with layers of type `application/vnd.dsse.envelope.v1+json`. The layer blob is a DSSE envelope containing the in-toto statement. The layer descriptor carries a `predicateType` annotation identifying the attestation type, and `dev.cosignproject.cosign/signature` is empty since the signature is embedded in the envelope. Each attestation event appends a new layer.
110+
111+
```json
112+
{
113+
"schemaVersion": 2,
114+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
115+
"config": {
116+
"mediaType": "application/vnd.oci.image.config.v1+json",
117+
"size": 342,
118+
"digest": "sha256:078640..."
119+
},
120+
"layers": [
121+
{
122+
"mediaType": "application/vnd.dsse.envelope.v1+json",
123+
"size": 676,
124+
"digest": "sha256:d222f2...",
125+
"annotations": {
126+
"dev.cosignproject.cosign/signature": "",
127+
"dev.sigstore.cosign/bundle": "{...}",
128+
"predicateType": "https://cosign.sigstore.dev/attestation/v1"
129+
}
130+
}
131+
]
132+
}
133+
```
134+
135+
This is the format produced by cosign 1.x and 2.x, and full verification of the transparency log entry requires online access to Rekor.
136+
137+
## Scenario 1: New Bundle Format + OCI 1.1 Referrers
138+
139+
When using the default new bundle format against a registry that supports the OCI 1.1 specification, cosign will store signatures and attestations using the OCI 1.1 referrers API.
140+
141+
### Signing
142+
143+
```shell
144+
# Key-based signing
145+
cosign sign --key cosign.key $IMAGE
146+
147+
# Keyless signing (default)
148+
cosign sign $IMAGE
149+
```
150+
151+
The signature is stored as an OCI 1.1 referrer with the new sigstore bundle format.
152+
153+
### Verification
154+
155+
```shell
156+
# Key-based verification
157+
cosign verify --key cosign.pub $IMAGE
158+
159+
# Keyless verification
160+
cosign verify \
161+
--certificate-identity=name@example.com \
162+
--certificate-oidc-issuer=https://accounts.example.com \
163+
$IMAGE
164+
```
165+
166+
### Attestations
167+
168+
```shell
169+
# Create attestation
170+
cosign attest \
171+
--key cosign.key \
172+
--type slsaprovenance \
173+
--predicate predicate.json \
174+
$IMAGE
175+
176+
# Verify attestation
177+
cosign verify-attestation \
178+
--key cosign.pub \
179+
--type slsaprovenance \
180+
$IMAGE
181+
```
182+
183+
The attestation is stored as an OCI 1.1 referrer.
184+
185+
## Scenario 2: New Bundle Format + OCI 1.0 (Referrers Tag Schema Fallback)
186+
187+
When using the default new bundle format against a registry that does not support the OCI 1.1 referrers API, cosign automatically falls back to the **referrers tag schema** defined in the OCI Distribution Specification. Artifacts are stored under a `sha256-<digest>` index tag, and both signing and verification work transparently.
188+
189+
> **Note:** This fallback only works for clients that implement the OCI Distribution Specification 1.1 referrers tag schema. Tools written to look for old-format `.sig` tags will not find new-format signatures stored this way.
190+
191+
### Signing
192+
193+
```shell
194+
# Key-based signing
195+
cosign sign --key cosign.key $IMAGE
196+
197+
# Keyless signing
198+
cosign sign $IMAGE
199+
```
200+
201+
The signature is stored under a `sha256-<digest>` index tag (not a `.sig` tag).
202+
203+
### Verification
204+
205+
```shell
206+
# Key-based verification
207+
cosign verify --key cosign.pub $IMAGE
208+
209+
# Keyless verification
210+
cosign verify \
211+
--certificate-identity=name@example.com \
212+
--certificate-oidc-issuer=https://accounts.example.com \
213+
$IMAGE
214+
```
215+
216+
### Attestations
217+
218+
```shell
219+
# Create attestation
220+
cosign attest \
221+
--key cosign.key \
222+
--type slsaprovenance \
223+
--predicate predicate.json \
224+
$IMAGE
225+
226+
# Verify attestation
227+
cosign verify-attestation \
228+
--key cosign.pub \
229+
--type slsaprovenance \
230+
$IMAGE
231+
```
232+
233+
The attestation is stored under the same `sha256-<digest>` index tag alongside the signature.
234+
235+
## Scenario 3: Old Bundle Format + OCI 1.1 Referrers (Signatures Only)
236+
237+
This mode stores signatures using the OCI 1.1 referrers API while using the old bundle format. Note that **attestations are not supported** with OCI 1.1 in this mode, they will fall back to tag-based storage.
238+
239+
### Signing
240+
241+
```shell
242+
# Requires COSIGN_EXPERIMENTAL=1 environment variable
243+
COSIGN_EXPERIMENTAL=1 cosign sign \
244+
--key cosign.key \
245+
--new-bundle-format=false \
246+
--use-signing-config=false \
247+
--registry-referrers-mode=oci-1-1 \
248+
$IMAGE
249+
```
250+
251+
The signature is stored as an OCI 1.1 referrer (discoverable via `/referrers/<digest>` endpoint).
252+
253+
### Verification
254+
255+
```shell
256+
cosign verify \
257+
--key cosign.pub \
258+
--new-bundle-format=false \
259+
--experimental-oci11=true \
260+
$IMAGE
261+
```
262+
263+
> **Important:** The `--experimental-oci11` flag is required for verification to discover signatures stored via the referrers API.
264+
265+
## Scenario 4: Old Bundle Format + Tag-based (OCI 1.0)
266+
267+
Use this mode with registries that don't support OCI 1.1.
268+
269+
### Signing
270+
271+
```shell
272+
# With key-based signing (uploads to Rekor transparency log)
273+
cosign sign --key cosign.key \
274+
--new-bundle-format=false \
275+
--use-signing-config=false \
276+
$IMAGE
277+
278+
# With keyless signing
279+
cosign sign \
280+
--new-bundle-format=false \
281+
--use-signing-config=false \
282+
$IMAGE
283+
```
284+
285+
The signature is stored at a tag: `sha256-<digest>.sig`
286+
287+
### Verification
288+
289+
```shell
290+
# Key-based verification
291+
cosign verify --key cosign.pub \
292+
--new-bundle-format=false \
293+
$IMAGE
294+
295+
# Keyless verification
296+
cosign verify \
297+
--new-bundle-format=false \
298+
--certificate-identity=name@example.com \
299+
--certificate-oidc-issuer=https://accounts.example.com \
300+
$IMAGE
301+
```
302+
303+
### Attestations
304+
305+
```shell
306+
# Create attestation (uploads to Rekor)
307+
cosign attest \
308+
--key cosign.key \
309+
--new-bundle-format=false \
310+
--use-signing-config=false \
311+
--type slsaprovenance \
312+
--predicate predicate.json \
313+
$IMAGE
314+
315+
# Verify attestation
316+
cosign verify-attestation \
317+
--key cosign.pub \
318+
--new-bundle-format=false \
319+
--type slsaprovenance \
320+
$IMAGE
321+
```
322+
323+
The attestation is stored as a tag: `sha256-<digest>.att`
324+
325+
326+
## Discovering Referrers
327+
328+
You can discover all artifacts associated with an image using standard OCI tools, independently of cosign. This is useful for auditing what has been stored, debugging verification failures, or building tooling that consumes signatures and attestations.
329+
330+
### List all referrers
331+
332+
```shell
333+
oras discover registry.example.com/myrepo@sha256:abc123...
334+
```
335+
336+
For an image with both a signature and attestation in new bundle format, both appear under the same `artifactType`:
337+
338+
```
339+
registry.example.com/myrepo@sha256:abc123...
340+
└── application/vnd.dev.sigstore.bundle.v0.3+json
341+
├── sha256:b6c621...
342+
└── sha256:d7e892...
343+
```
344+
345+
For old-format signatures stored via the referrers API, the `artifactType` is distinct:
346+
347+
```
348+
registry.example.com/myrepo@sha256:abc123...
349+
└── application/vnd.dev.cosign.artifact.sig.v1+json
350+
└── sha256:6d2cd8...
351+
```
352+
353+
### Fetch and inspect a specific artifact
354+
355+
To determine whether a new-format referrer is a signature or attestation, fetch the manifest to get the layer digest, then decode the DSSE envelope payload in the layer blob:
356+
357+
```shell
358+
# Step 1: fetch the manifest to get the layer digest
359+
oras manifest fetch registry.example.com/myrepo@sha256:<referrer-digest> | jq '.layers[0].digest'
360+
361+
# Step 2: fetch the layer and decode the predicateType from the DSSE payload
362+
oras blob fetch --output - registry.example.com/myrepo@sha256:<layer-digest> \
363+
| jq '.dsseEnvelope.payload | @base64d | fromjson | .predicateType'
364+
```
365+
366+
For a signature this returns `https://sigstore.dev/cosign/sign/v1`. For an attestation it returns the predicate type (e.g. `https://slsa.dev/provenance/v1` for SLSA provenance).
367+
368+
### Tag-based storage (OCI 1.0 fallback)
369+
370+
When cosign uses tag-based storage (Scenarios 2 and 4), artifacts are not accessible via the referrers API. The artifacts can be pulled directly using the appropriate tag format:
371+
372+
```shell
373+
# New format fallback: referrers tag schema index
374+
oras manifest fetch registry.example.com/myrepo:sha256-<image-digest>
375+
376+
# Old format: individual signature and attestation tags
377+
oras manifest fetch registry.example.com/myrepo:sha256-<image-digest>.sig
378+
oras manifest fetch registry.example.com/myrepo:sha256-<image-digest>.att
379+
```

0 commit comments

Comments
 (0)