Sigstore published the Cosign v3.0 GA announcement on the Sigstore blog with the headline change that "the four behaviours that were opt-in in v2.6 are defaults in v3". For teams that did the v2.6 staged migration cleanly, v3 should be near a no-op. For teams that skipped v2.6, v3 is going to surprise CI pipelines on the day they upgrade. This guide is the plan we used to move three signing pipelines (GitHub Actions, Tekton, an internal admission controller) from v2.4-era invocations directly to v3.0 in a controlled four-week rollout.
What changes at the default level in v3.0?
Four behaviours flip. (1) --new-bundle-format becomes the default; signatures and attestations are written as bundles, not as separate OCI layers. (2) --trusted-root becomes the default; Cosign loads trusted_root.json from $XDG_CONFIG_HOME/sigstore/trusted_root.json if it exists, falling back to the embedded public-good root otherwise. (3) --use-signing-config becomes the default; the service URLs for Fulcio, Rekor, and the TSA come from a signing_config.json rather than CLI flags. (4) cosign attest expects a fully formed in-toto statement when --statement is passed; the legacy predicate-only mode requires an explicit --predicate flag and emits a deprecation warning.
The behaviours can still be disabled in v3 (the relevant flags accept =false), but the defaults are inverted from v2. Anything in CI that explicitly passed --new-bundle-format=false will keep working; anything that depended on the absence of bundle output silently will not.
Which pipelines break first?
Three patterns we hit. First, verifier scripts that parse separate .sig and .cert OCI layers fail because the layers are no longer there — the verification material is in the bundle. Second, admission controllers that pin to a hardcoded Rekor URL inside the binary will keep verifying against the wrong instance if the trusted-root file points elsewhere. Third, attestation generation pipelines that wrap a predicate inside a custom Statement, then pass --predicate, end up double-wrapping and producing an invalid statement. All three failure modes are loud — they error rather than silently produce broken artefacts — but they surface only at signing or verify time, not at install time, so they catch teams off guard.
What does a working v3 sign-and-verify look like end-to-end?
The simplest production-grade invocation:
# Sign in CI (v3 defaults)
cosign sign \
--yes \
--output-signature signature.bundle \
registry.internal/myapp:${GIT_SHA}
# Generate a SLSA provenance attestation from a full in-toto statement
cosign attest \
--yes \
--statement build-provenance.intoto.jsonl \
--output-attestation provenance.bundle \
registry.internal/myapp:${GIT_SHA}
# Verify with a private trusted root
cosign verify \
--trusted-root /etc/sigstore/trusted_root.json \
--certificate-identity-regexp "^https://github.com/acme/.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--bundle signature.bundle \
registry.internal/myapp:${GIT_SHA}
cosign verify-attestation \
--trusted-root /etc/sigstore/trusted_root.json \
--type slsaprovenance1 \
--certificate-identity-regexp "^https://tekton.internal/builder/.*" \
--bundle provenance.bundle \
registry.internal/myapp:${GIT_SHA}
The --trusted-root and --certificate-identity-regexp flags are not new, but the way they compose in v3 is cleaner: the trusted root contains the CA chain, the Rekor key, and the timestamp authority, and the identity regexp is the only policy artefact a verifier needs to maintain.
How do we handle multiple Rekor instances during the rotation?
This is the part v2.6 introduced and v3 makes routine. A trusted_root.json can list multiple Rekor instances, each with a validity window. During a migration from Rekor v1 to v2, the trusted root contains both; clients verify against whichever matches the bundle's transparency log entry. We use this pattern internally: our trusted root lists the public-good Rekor for legacy signatures and our private Rekor v2 for new signatures, and a future cutover will drop the public-good entry.
{
"tlogs": [
{
"baseUrl": "https://rekor.sigstore.dev",
"validFor": {"start": "2023-01-01T00:00:00Z", "end": "2026-06-01T00:00:00Z"}
},
{
"baseUrl": "https://rekor.internal:443",
"validFor": {"start": "2025-09-01T00:00:00Z"}
}
]
}
What about backwards compatibility with existing signatures?
v3 verifies v2-era signatures and attestations without ceremony — the legacy formats are still readable. The only constraint is that the verifier must have access to the relevant Rekor instance and Fulcio CA chain via its trusted root. If your organisation has signed against the public-good instance for years and is now moving to a private deployment, leave the public-good entries in the trusted root until the legacy artefacts are out of circulation. There is no need to re-sign existing release artefacts.
What is the rollback plan if v3 breaks production?
We keep v2.6.2 binaries pinned alongside v3.0 in our build image for at least one quarter post-cutover. The rollback is a one-line change in the pipeline that swaps cosign for cosign-v2. Because v2.6 produced new-format bundles when invoked with --new-bundle-format, every artefact our v3 pipelines produced is verifiable with v2.6 too — there is no asymmetric format we cannot reverse. The only situation requiring a real fallback is if a CI step explicitly relies on a v3-only flag (we found one — --registry-referrers-mode oci-1-1); we documented those as "no-rollback" steps and accepted the risk.
How should teams sequence the upgrade?
Four weeks. Week 1: deploy v3 in shadow mode (sign artefacts but do not gate deploys). Week 2: switch verifier admission controllers to v3, keep signing on v2.6. Week 3: switch signing to v3 in non-critical pipelines. Week 4: switch critical pipelines and remove the v2.6 fallback from the build image. If anything breaks, it surfaces in week 1 or 2 against artefacts that are not yet promoted to production, which is the cheapest place to find it.
How Safeguard Helps
Safeguard normalises Cosign v2 and v3 bundles into a single attestation graph, so a migration in progress does not fragment the policy view. Griffin AI tracks signature provenance across the fleet and flags artefacts that lost a signature during the cutover or that point at a deprecated trusted root. Policy gates can enforce "v3 bundle plus matching SLSA provenance statement" as a release prerequisite, and the trust-root inventory in Safeguard makes it possible to audit which Fulcio CAs, Rekor instances, and TSAs are in scope across every environment. For teams running the Cosign v2-to-v3 migration today, Safeguard is the cross-cutting view that turns four weeks of pipeline rewrites into a single dashboard.