Skip to main content

Keyless Signing Won: What Rekor v2 and cosign v3 Mean for Verifying Every Image at Admission

12 min readDora NodaDora Noda
Share
On this page

In October 2025, the Sigstore project flipped the default it had been building toward for four years: keyless signing — short-lived certificates bound to a workload's OIDC identity, logged in a public transparency log — stopped being the new way to sign and became the only way that matters. Rekor v2 went GA on a cheaper tile-backed log, cosign v3 made the self-contained bundle the unit of signing, and across 2026 the ecosystem followed: release pipelines now ship a .sigstore.json bundle per artifact as a matter of course, and Open Component Model cut a breaking release to bundle Fulcio certificates instead of raw public keys.

If you run a platform that builds container images from source — a PaaS turning git pushes into running services — this changes the verification side of your supply chain more than the signing side. The old question at deploy time was "do I have the right public key for this image, and is the signature logged?" The new question is simpler and stronger: "was this image built by an identity I allow, and can I prove it from the bundle alone?" Here is the before and after in one table:

StepBefore (keys + Rekor v1)After (identity + Rekor v2 bundles)
What the signer holdsLong-lived private key, or an OIDC flow bolted onto key-based toolingNothing durable: a ~10-minute Fulcio certificate bound to the CI workflow identity
What ships with the artifactDetached signature plus a certificate and a Rekor entry fetched separatelyOne .sigstore.json bundle: certificate, signature, inclusion proof, RFC 3161 timestamp
What the verifier looks upThe signer's public key, per image, from somewhere you maintainThe Sigstore trust root via TUF plus your own allowlist of builder identities
Deploy-time checkcosign verify --key <pubkey> against a key registry you keep freshcosign verify --certificate-identity-regexp <allowed builders> --certificate-oidc-issuer <issuer>
Transparency logRekor v1, eleven entry types, signed entry timestampsRekor v2, two entry types (hashedrekord, dsse), timestamps from a TSA

The rest of this post unpacks that table: what Rekor v2 actually changed, what cosign v3 breaks in existing pipelines, what Open Component Model's migration teaches about doing it right, how to turn identity-based verification into an admission-time fleet default, and — just as important — where verification stops.

What Rekor v2 actually changed

Rekor v2 went GA on October 10, 2025, and the headline from the announcement is operational, not cryptographic: "cheaper to run, simpler to maintain." The backend moved from the original Rekor implementation to a tile-backed transparency log built on Tessera, the same tlog-tiles design that underpins modern Certificate Transparency logs. That is why the Sigstore team could afford to keep the public log free while usage kept climbing.

For operators, the v1-to-v2 differences that matter are these:

Rekor v1Rekor v2
BackendOriginal Rekor serverTessera tile-backed log
Entry typesEleven (hashedrekord, dsse, intoto, rekord, helm, tuf, cose, and more)Two: hashedrekord for artifacts, dsse for attestations
TimestampsSigned entry timestamps (SETs) issued by the logNone from the log; clients fetch RFC 3161 timestamps from a timestamp authority
ShardingSingle long-lived instance at rekor.sigstore.devPer-period shards (the 2025 shard is log2025-1.rekor.sigstore.dev)
StatusMaintenance mode since October 2025, retirement in 2026Current

Three consequences fall out of that table:

  • Timestamps moved. If your verifiers still expect a SET inside the bundle, they will break against v2-signed artifacts: the timestamp now arrives as a separate RFC 3161 token (cosign surfaces this as --use-signed-timestamps), and both halves travel in the bundle.
  • Clients got simpler. The entry-type cull means clients only implement two code paths, which is part of why Go, Python, and Java clients all shipped v2 support alongside cosign v2.6.0, with a refreshed conformance suite to prove it.
  • Shard URLs rotate. The GA announcement explicitly warns against hardcoding the 2025 URL into pipelines, because the instance will be turned down when a new shard deploys. Trust roots and log URLs now flow through TUF and the SigningConfig, not through strings pasted into CI YAML.

The practical upshot: a bundle produced today is far more self-contained than anything Rekor v1 produced. Certificate, signature, inclusion proof, timestamp — everything a verifier needs, in one JSON file, resolvable against a TUF-distributed trust root. That self-containment is what makes the admission-time story in the second half of this post feasible.

What cosign v3 breaks in your pipeline

cosign v3.0.0 shipped in October 2025 alongside Rekor v2 support, and it is a genuine major release, not a marketing one. The breaking changes cluster around one idea: the bundle is now the unit of signing, and the loose collection of sidecar files is gone.

The most visible break is in sign-blob. The --output-signature and --output-certificate flags are removed; you must pass --bundle, which packs the signature, the Fulcio certificate, and the transparency-log material into a single file:

bash
# cosign v2: signature and certificate as separate sidecars
cosign sign-blob --output-signature artifact.sig \
  --output-certificate artifact.pem artifact.tar.gz
 
# cosign v3: everything in one bundle
cosign sign-blob --bundle artifact.sigstore.json artifact.tar.gz

Three more migration items come with it. Go programs import github.com/sigstore/cosign/v3 now, since the module path bumped with the major version. CI workflows must upgrade to cosign-installer v4, which is the first installer line that ships cosign v3 (v2.6.1 is planned as the final v2 release, so staying behind has an expiry date). And keyless v3 signatures carry an RFC 3161 timestamp by default, which is what keeps them verifiable after the short-lived Fulcio certificate expires — without it, a verifier checking a week-old signature has no proof the certificate was valid at signing time.

Then there is the gotcha that actually pages people: cosign v3 changed OIDC token handling in GitHub Actions. GitHub no longer auto-injects an ID token when SIGSTORE_ID_TOKEN is missing, so workflows must add the id-token: write permission, explicitly request a token with the sigstore audience, and export it before any signing step. Miss that step and CI fails with the memorably unhelpful error getting ID token: executing OIDC flow: failed to start browser — cosign falling back to an interactive flow on a headless runner. If your signing worked on v2 and breaks on v3 with that message, the token export is the first thing to check.

Case study: Open Component Model v0.36.0

The clearest worked example of the migration in 2026 comes from Open Component Model, whose PR #1726 — shipped in ocm v0.36.0 — bundles both halves of the transition into one release with two declared breaking changes.

Breaking change one is the conceptual heart of the whole keyless-mainstream moment: OCM's keyless signatures now bundle the short-lived Fulcio certificate instead of just a raw public key. Previously, an OCM signature stored only the public key in the Rekor entry, which meant a verifier had to independently know whose key that was — the identity binding lived outside the artifact, in whatever key registry the verifier maintained. Now the certificate travels inside the signature, conforming to the Sigstore Bundle spec, and the identity is self-describing. To preserve compatibility, OCM introduced a new sigstore-v2 signing algorithm for new signatures while keeping the legacy sigstore algorithm verifiable:

bash
# New signatures: certificate bundled, Sigstore Bundle compliant
ocm sign componentversion --signature mysig --algorithm sigstore-v2 --keyless <component-version>
 
# Verification picks the algorithm from the signature name
ocm verify componentversion --signature mysig --keyless <component-version>

Breaking change two is the cosign v2-to-v3 upgrade itself, including the GitHub Actions OIDC handling change described above — OCM's migration notes walk users through the id-token: write permission and the explicit SIGSTORE_ID_TOKEN export.

Why does this release matter beyond OCM users? Because it is the pattern every artifact system converges on: stop storing keys, start storing certificates, and let the bundle carry the identity. A raw public key answers "which key signed this" and leaves "should I trust that key" as an exercise for the verifier's key-management process. A Fulcio certificate answers "which workload identity signed this, as attested by which OIDC issuer, at a time the transparency log witnessed" — and the verifier's remaining job shrinks to checking that identity against an allowlist. That shrinkage is the entire economic argument for keyless at fleet scale: the per-artifact key hunt disappears, replaced by one trust root and one policy.

Admission-time verification as a fleet default

This is where the 2026 stack pays off for a platform that builds tenant images from source. When every build pipeline signs keylessly and every signature carries its builder identity, deploy-time verification stops being a per-image errand and becomes a single fleet-wide policy: only run images built by identities on the allowlist.

The primitive is cosign verify with identity constraints instead of a key:

bash
cosign verify registry.example.com/tenant/app@sha256:<digest> \
  --certificate-identity-regexp '^https://github.com/my-org/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

No --key flag, no key file, no per-tenant key onboarding. The Fulcio root comes from the TUF trust root, the Rekor inclusion proof and timestamp come from the bundle the registry stores alongside the image, and the only thing you author is the identity policy: which OIDC issuer you trust and which workflow identities may ship to this fleet. A new tenant's first deploy verifies on day one with zero key-exchange ceremony, because there are no keys to exchange — there is only the question "did our builder build this," answered by cryptography instead of a spreadsheet.

At admission time, that check belongs in front of the kubelet, not in CI. The two established enforcement points are Sigstore's policy-controller and Kyverno's verifyImages rules, both of which evaluate image signatures (and attestations) in a validating admission webhook and reject pods whose images are unsigned or signed by an identity outside the policy. Deployed as a fleet default, the failure mode inverts usefully: instead of hoping every pipeline remembered to sign, any image that cannot prove an allowed builder identity simply never schedules. Unsigned third-party images a tenant drags in, stale images from before the signing rollout, typosquatted base images — all of them fail the same gate, with the denial logged at the admission webhook where the platform team can see it.

A realistic rollout runs in three stages:

  1. Sign everywhere in the build fleet and ship bundles with images, verifying in audit mode so you can measure the gap between "images we build" and "images tenants actually run."
  2. Flip admission to enforce for platform-built namespaces while keeping a documented exemption path for the long tail.
  3. Close the exemptions on a schedule, tenant by tenant.

The audit stage matters more than it looks: it is where you discover the images nobody owns, which are precisely the ones an attacker would prefer.

Where verification stops

"Signed by default" is a tempting tenant-facing claim, and keyless makes it cheap enough to be true on day one. But identity-based verification proves who built the image — not that the builder was trustworthy, and not that the image is safe. Before the claim goes on a pricing page, four boundaries need to be explicit:

A valid signature from a compromised builder verifies fine. If an attacker lands in your build workflow — a poisoned dependency, a malicious pull request that CI built and signed, leaked OIDC minting rights — the resulting image carries a perfectly valid keyless signature from an allowed identity. Admission verification answers "was this built by our pipeline," and the attacker's image truthfully was. The mitigation is everything upstream of signing: pinned dependencies, required reviews on the workflow files themselves, and SLSA-style provenance attestations that record exactly which source revision and build steps produced the image, so "built by us" can be graded into "built by us from reviewed source."

Identity is only as strong as the issuer. Trusting token.actions.githubusercontent.com means trusting GitHub's OIDC issuance for your organization — including every workflow in every repository that can mint a token with your org's identity claims. Scope --certificate-identity-regexp to the specific repositories and workflow files that are allowed to ship, not just the org prefix, and treat a new workflow file gaining signing rights as a privilege grant worth reviewing.

Signatures say nothing about contents. A signed image can still ship a critical CVE, a leaked secret baked into a layer, or a dependency with a fresh advisory. Keyless verification replaces the key-management half of supply-chain security; it does not replace scanning (Trivy, Grype), SBOM attestations, or policy that blocks images with known-critical vulnerabilities. The bundle can carry those attestations — cosign attest signs SLSA provenance and vulnerability-scan results with the same keyless flow — but someone still has to check them at admission.

The transparency log is a detection control, not a prevention control. Rekor's inclusion proof lets anyone audit that a signature existed at a given time, which is what makes covert signing detectable — but detection happens after the fact. Pair the log with monitoring that alerts on unexpected signing identities for your repositories, so a valid-but-surprising signature gets investigated rather than silently admitted.

None of this diminishes the 2026 shift; it scopes it. Keyless verification moves the fleet from "we hope images are what they claim" to "every image proves its builder, and unknown builders never schedule." That is a large, real, enforceable upgrade — as long as the marketing stops one step short of "therefore every image is trustworthy."

Conclusion

Three milestones made 2026 the year keyless won: Rekor v2's GA gave the transparency log a sustainable backend and a bundle format that carries everything a verifier needs; cosign v3 made that bundle the only shape signing produces; and ecosystem projects like Open Component Model did the unglamorous breaking-release work of moving real artifact formats onto certificates instead of keys. With Rekor v1 heading for retirement, the migration is not optional on any interesting timeline — it is just a question of whether you schedule it or discover it.

For a platform team, the action list is short: upgrade verifiers to handle v2 bundles and TSA timestamps, move signing to cosign v3 with explicit OIDC token handling, scope identity allowlists to the workflows that may ship, and enforce the result at admission with policy-controller or Kyverno — in audit mode first, then for real. The reward is a fleet where provenance is structural: every running image can name its builder, and the ones that cannot never start.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex