Skip to content

sigstore: add Rekor v2 opt-in for cosign signing - #1176

Merged
crazy-max merged 2 commits into
mainfrom
cosign-rekor-v2
Jul 23, 2026
Merged

sigstore: add Rekor v2 opt-in for cosign signing#1176
crazy-max merged 2 commits into
mainfrom
cosign-rekor-v2

Conversation

@crazy-max

@crazy-maxcrazy-max commented Jun 11, 2026

Copy link
Copy Markdown
Member

needs #1208

This updates the Sigstore signing flow for cosign 3.1.1 while keeping older cosign versions working with their existing flags.

The signing config creation now supports Rekor v2 as an explicit opt-in through rekorV2. When that option is enabled, transparency log upload is enabled, and cosign is 3.1.1 or newer, the toolkit uses --with-default-rekor-v2=true. The default path continues to use --with-default-services=true, so cosign 3.1.1 does not switch to Rekor v2 unless callers request it.

The cosign command arguments now omit --new-bundle-format for cosign 3.1.1 and newer because that bundle format is already the default and the flag is deprecated. Older cosign 3.0.x versions still receive --new-bundle-format, which keeps the existing signing and verification flows compatible.

The Rekor upload log now avoids linking to search.sigstore.dev when Rekor v2 is used, because there is no Rekor v2 UI there yet. In that case the log reports the Rekor v2 transparency log index directly.

This intentionally keeps --experimental-oci11 for verification because cosign 3.1.1 still needs that flag for the OCI referrer behavior used by these signatures. Removing it now would be premature even though upstream marks it as deprecated for future versions.

The integration coverage now runs the default signing path across the supported cosign versions and adds Rekor v2 opt-in coverage for cosign versions that support it. This applies to both attestation manifest signing and provenance blob signing.

@crazy-max

Copy link
Copy Markdown
MemberAuthor

With cosign 3.1.1 it creates this signing config: https://github.com/docker/actions-toolkit/actions/runs/27343642457/job/80786588245?pr=1176#step:10:376

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign signing-config create --with-default-rekor-v2=true --out=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json
{
"mediaType": "application/vnd.dev.sigstore.signingconfig.v0.2+json",
"caUrls": [
{
"url": "https://fulcio.sigstore.dev/",
"majorApiVersion": 1,
"validFor": {
"start": "2022-04-13T20:06:15Z"
},
"operator": "sigstore.dev"
}
],
"oidcUrls": [
{
"url": "https://oauth2.sigstore.dev/auth",
"majorApiVersion": 1,
"validFor": {
"start": "2022-04-13T20:06:15Z"
},
"operator": "sigstore.dev"
}
],
"rekorTlogUrls": [
{
"url": "https://log2025-1.rekor.sigstore.dev/",
"majorApiVersion": 2,
"validFor": {
"start": "2026-01-01T00:00:00Z"
},
"operator": "sigstore.dev"
},
{
"url": "https://rekor.sigstore.dev/",
"majorApiVersion": 1,
"validFor": {
"start": "2021-01-12T11:53:27Z"
},
"operator": "sigstore.dev"
}
],
"rekorTlogConfig": {
"selector": "ANY"
},
"tsaUrls": [
{
"url": "https://timestamp.sigstore.dev/api/v1/timestamp",
"majorApiVersion": 1,
"validFor": {
"start": "2025-07-04T00:00:00Z"
},
"operator": "sigstore.dev"
}
],
"tsaConfig": {
"selector": "ANY"
}
}

Example of signed attestation manifest:

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign sign --yes --oidc-provider github-actions --registry-referrers-mode oci-1-1 --signing-config=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab
Uploaded to Rekor transparency log: [https://search.sigstore.dev?logIndex=5035492](https://search.sigstore.dev/?logIndex=5035492)
Signature manifest pushed: https://oci.dag.dev/?referrers=ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab

The https://search.sigstore.dev?logIndex=5035492 is wrong for rekor v2 though. Don't think there is a Rekor v2 search UI yet

@crazy-max

Copy link
Copy Markdown
MemberAuthor

Example of signed attestation manifest:

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign sign --yes --oidc-provider github-actions --registry-referrers-mode oci-1-1 --signing-config=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab
Uploaded to Rekor transparency log: [https://search.sigstore.dev?logIndex=5035492](https://search.sigstore.dev/?logIndex=5035492)
Signature manifest pushed: https://oci.dag.dev/?referrers=ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab

The https://search.sigstore.dev?logIndex=5035492 is wrong for rekor v2 though. Don't think there is a Rekor v2 search UI

So for the rekor log entry 5035492 we need the Tessera tiled path encoding and Rekor v2 stores entries in bundles of 256 entries so for this log index:

bundle_number = floor(5035492 / 256)
= 19669

Then 19669 formatted as 3-digit decimal groups from left to right:

19669 -> 019 / 669

Which gives: https://log2025-1.rekor.sigstore.dev/api/v2/tile/entries/x019/669

I attached the output here.

bundle.zip

Decoding is tricky so I used an agent for this:

{
"logIndex": 5035492,
"rekorV2BundlePath": "x019/669",
"bundleIndex": 19669,
"offsetZeroBased": 228,
"offsetOneBased": 229,
"apiVersion": "0.0.2",
"kind": "hashedrekord",
"data": {
"algorithm": "SHA2_256",
"digestBase64": "bL9f6pc9Nq5yzruKYA+iboF6MVhXK6Gfx5vflh1PMLU=",
"digestHex": "6cbf5fea973d36ae72cebb8a600fa26e817a3158572ba19fc79bdf961d4f30b5"
},
"signature": {
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
"signatureBase64": "MEQCIAS2+PKs/J3v27PLfHSM0SdAoX7GU3l5Ybd3MwWl4BguAiBBPzJfhgIWvjFuyVcyoYWj/O8uwKV/yjDrgZIeAdEtnA==",
"ecdsaR": "04b6f8f2acfc9defdbb3cb7c748cd12740a17ec653797961b7773305a5e0182e",
"ecdsaS": "413f325f860216be316ec95732a185a3fcef2ec0a57fca30eb81921e01d12d9c"
},
"certificate": {
"subject": "(empty)",
"issuer": "CN=sigstore-intermediate,O=sigstore.dev",
"serialHex": "0x1c16ae92f16578fda09f0d1b34127f48c2004f0c",
"validFromUtc": "2026-06-11T11:32:09+00:00",
"validUntilUtc": "2026-06-11T11:42:09+00:00",
"fingerprintSha256": "35477077f6f33a8ec2217cf620b3bad2818929db96193363a945e05fa596f6ea",
"subjectAltNameUri": "https://github.com/docker/actions-toolkit/.github/workflows/test.yml@refs/pull/1176/merge"
},
"githubOidcIdentity": {
"oidcIssuer": "https://token.actions.githubusercontent.com",
"workflowTrigger": "pull_request",
"workflowSha": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
"workflowName": "test",
"workflowRepository": "docker/actions-toolkit",
"workflowRef": "refs/pull/1176/merge",
"runnerEnvironment": "github-hosted",
"sourceRepositoryUri": "https://github.com/docker/actions-toolkit",
"sourceRepositoryDigest": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
"sourceRepositoryRef": "refs/pull/1176/merge",
"sourceRepositoryIdentifier": "589268852",
"sourceRepositoryOwnerUri": "https://github.com/docker",
"sourceRepositoryOwnerIdentifier": "5429470",
"buildConfigUri": "https://github.com/docker/actions-toolkit/.github/workflows/test.yml@refs/pull/1176/merge",
"buildConfigDigest": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
"buildTrigger": "pull_request",
"runInvocationUri": "https://github.com/docker/actions-toolkit/actions/runs/27343642457/attempts/1",
"sourceRepositoryVisibilityAtSigning": "public",
"subject": "repo:docker/actions-toolkit:pull_request"
}
}

Original Rekor entry, with the large cert decoded separately above:

{
"apiVersion": "0.0.2",
"kind": "hashedrekord",
"spec": {
"hashedRekordV002": {
"data": {
"algorithm": "SHA2_256",
"digest": "bL9f6pc9Nq5yzruKYA+iboF6MVhXK6Gfx5vflh1PMLU="
},
"signature": {
"content": "MEQCIAS2+PKs/J3v27PLfHSM0SdAoX7GU3l5Ybd3MwWl4BguAiBBPzJfhgIWvjFuyVcyoYWj/O8uwKV/yjDrgZIeAdEtnA==",
"verifier": {
"keyDetails": "PKIX_ECDSA_P256_SHA_256",
"x509Certificate": {
"rawBytes": "<base64 DER certificate; decoded above>"
}
}
}
}
}
}

@Hayden-IO For Rekor v2, it looks like entries are now exposed through Tessera entry bundles. I understand Rekor v2 removed the old search/index API and that entries are served as bundles, so I'm not asking for the old backend behavior necessarily. I'm mainly asking whether there will be a supported web UI or shareable permalink for inspecting a Rekor v2 entry by log index.

@crazy-max
crazy-max marked this pull request as ready for review June 29, 2026 10:16
@crazy-max
crazy-max marked this pull request as draft June 29, 2026 10:18
@crazy-max
crazy-maxforce-pushed the cosign-rekor-v2 branch 3 times, most recently from 069a00a to c6c9b9aCompareJuly 1, 2026 08:31
@crazy-max
crazy-max marked this pull request as ready for review July 1, 2026 08:31
@crazy-maxcrazy-max changed the title sigstore: handle cosign 3.1.1 signing defaultssigstore: add Rekor v2 opt-in for cosign signingJul 2, 2026
@Hayden-IO

Copy link
Copy Markdown

For Rekor v2, it looks like entries are now exposed through Tessera entry bundles. I understand Rekor v2 removed the old search/index API and that entries are served as bundles, so I'm not asking for the old backend behavior necessarily. I'm mainly asking whether there will be a supported web UI or shareable permalink for inspecting a Rekor v2 entry by log index.

We plan to have support in search.sigstore.dev for linking by index, I hacked something up in sigstore/rekor-search-ui#167.

We do plan to have a search index as well, but we don't yet know what will back the search index. We've just begun looking into using a verifiable index.

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
@crazy-max
crazy-max merged commit bac706c into mainJul 23, 2026
219 of 220 checks passed
@crazy-max
crazy-max deleted the cosign-rekor-v2 branch July 23, 2026 10:03
nickpell pushed a commit to cloudx-io/openauction that referenced this pull request Aug 24, 2026
Weekly `ratchet` refresh of the SHA-pinned GitHub Actions under
`.github/`. Two refs moved, both to the newest release inside their
existing `# ratchet:` constraint. No constraint comment was rewritten
and no workflow logic changed.
## Refs that moved
| Action | File | Constraint | Version | SHA |
|---|---|---|---|---|
| `aws-actions/amazon-ecr-login` | `.github/workflows/docker.yml` |
`@v2` (unchanged) | v2.1.6 → v2.1.7 |
`d539f0932e70871a027e9d5a9d8fc38589180a64` →
`03f1aad4c6c7ffd436567f42f9384779290529bd` |
| `docker/setup-buildx-action` | `.github/workflows/docker.yml` | `@v4`
(unchanged) | v4.2.0 → v4.3.0 |
`bb05f3f5519dd87d3ba754cc423b652a5edd6d2c` →
`37fe631027851001ddb9b187196cc803df7f5f0e` |
## Upstream changelog
**[aws-actions/amazon-ecr-login
v2.1.7](https://github.com/aws-actions/amazon-ecr-login/releases/tag/v2.1.7)**
(published 2026-08-19). The changelog entry contains a single
*Dependency Updates* section — no features, fixes, or breaking-change
entries.
- `@aws-sdk/client-ecr`, `@aws-sdk/client-ecr-public`,
`@aws-sdk/credential-providers`: 3.1065.0 → 3.1111.0
- `undici` (transitive): 6.24.0 → 6.28.0
- Development-only: `eslint`, `globals`, `@vercel/ncc`, plus upstream's
own CI action pins
- `action.yml` is byte-identical between v2.1.6 and v2.1.7, so inputs,
outputs, and the action runtime are unchanged
**[docker/setup-buildx-action
v4.3.0](https://github.com/docker/setup-buildx-action/releases/tag/v4.3.0)**
(published 2026-08-19). The release notes list only dependency bumps.
- `@docker/actions-toolkit`: 0.92.0 → 0.95.0
- `js-yaml` 5.2.0 → 5.3.0; `brace-expansion` 1.1.13 → 1.1.18, `postcss`
8.5.10 → 8.5.25, `undici` 6.27.0 → 6.28.0 (transitive)
- `action.yml` is byte-identical between v4.2.0 and v4.3.0
- The behaviour-relevant content in the toolkit range is: retries added
around GitHub release-metadata fetches
([actions-toolkit#1276](docker/actions-toolkit#1276),
confined to `src/github/github.ts`), an **opt-in** Rekor v2 path for
cosign signing
([actions-toolkit#1176](docker/actions-toolkit#1176)),
an `undock` helper update, and `@actions/cache` 6.1.0 → 6.2.0
Neither release is labelled breaking, and neither carries a
breaking-change section. Both are patch/minor releases within the major
this repository already pins.
## Risk assessment
Low. The diff is two SHA values in one workflow file.
- **No contract change.** Each action's `action.yml` is unchanged across
the bump, so the inputs this repository passes — `platforms:` for the
buildx setup step, and no inputs for the ECR login step — resolve
exactly as before.
- **No major held back.** After this update every ratchet-managed ref
under `.github/` sits at the tip of its declared constraint, and no
action has a newer major tag upstream than the one currently pinned.
Nothing needed `ratchet upgrade`, so no `# ratchet:` constraint comment
was rewritten.
- **PR CI does not exercise these two steps.** Both changed refs live in
`.github/workflows/docker.yml`, which is triggered by `workflow_run`
after the Go workflow completes and by `workflow_dispatch`; it does not
run on pull requests. PR CI therefore confirms the refs are pinned and
that pinning is idempotent, but the two updated actions are first
exercised by Docker Build after this merges to `main`. That is covered
in the post-merge section below.
- **Most likely observable effect** is the buildx toolkit's new retry on
release-metadata fetches, which makes buildx setup more tolerant of
transient GitHub API failures. The Rekor v2 addition is opt-in and this
workflow does not enable it.
- For the ECR login step, the AWS SDK bump is a routine cumulative range
and the step's behaviour — authenticating the local Docker client
against the account registry — is unchanged.
- No open upstream issues report regressions against either version.
## Pre-merge checklist
- [x] `mise run //:ratchet:update` applied; re-running it produces no
further diff
- [x] `mise run //:ratchet:lint` passes — every external ref is still
pinned
- [x] `mise run //:ratchet:pin` is idempotent — `git diff --exit-code`
is clean afterwards
- [x] Diff limited to two SHA pins in `.github/workflows/docker.yml`; no
constraint comment changed and no unrelated workflow edits
- [x] Upstream release notes reviewed for both bumps; neither is
labelled breaking
- [ ] PR CI green, including `Ratchet Lint`
## Post-merge verification
- [ ] Workflows on `main` reference the new pins
- [ ] The first Docker Build run on `main` after merge succeeds. This is
where both updated actions are first exercised, since `docker.yml` does
not run on pull requests: the buildx setup step on every run, and the
ECR login step on a publishing run.
<div><a
href="https://cursor.com/agents/bc-5a0208aa-ff1b-4944-bb4b-f90b8d2aa38c?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/automations/65e8572f-8209-11f1-a7d1-d6b4613131ce"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/view-automation-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/view-automation-light.png"><img
alt="View Automation" width="141" height="28"
src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a>&nbsp;</div>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@crazy-max@Hayden-IO