Safeguard
Supply Chain Security•

Cosign verify-blob bypass with legacy bundles: check your CI scripts

Cosign v3.1.3 and v2.6.5 fix a High advisory where identity pinning is skipped for legacy JSON bundles. Image verification is not affected, but blob checks may be.

Safeguard Security Team
5 min read

On 6 August 2026 the Sigstore project published GHSA-fx35-mq7g-6g98, a High severity advisory (CVSS 7.4) titled "Verification bypass via public key in legacy bundle", and shipped fixes in Cosign v3 3.1.3 and v2.6.5. When a legacy JSON bundle carried a bare public key where a certificate should be, cosign verify-blob skipped the identity checks and still printed Verified OK. Teams that verify release archives, binaries or SBOM files with keyless signing are the ones to look at.

What's affected

The advisory is specific about scope:

  • Affected: cosign verify-blob and cosign verify-blob-attestation when given a legacy JSON bundle. Cosign v3 up to and including 3.1.2 (fixed in v3.1.3), and Cosign v2 up to and including 2.6.4 (fixed in v2.6.5).
  • Not affected: container image verification with cosign verify and cosign verify-attestation, and verification that uses the standardized Sigstore protobuf bundle format, which is the default in Cosign v3.

The root cause was a silent fallback. If the cert field of a legacy bundle failed to parse as an X.509 certificate, Cosign loaded the contents as a raw public key. Once that verifier was set, certificate chain validation and policy checks were skipped, so the certificate identity and OIDC issuer flags were ignored. The signature only had to be valid for the key the attacker supplied. The advisory adds a second effect: a key passed with the key flag could be overwritten by the key inside the bundle.

How to check if you're exposed

Find the version first, on every runner and developer machine:

cosign version

Then search your repositories, CI definitions and install scripts for blob verification:

grep -rEn "verify-blob(-attestation)?" .github .gitlab-ci.yml scripts Makefile Dockerfile 2>/dev/null

For each hit, check what the bundle file is. A legacy bundle is a JSON file with a cert field. A protobuf bundle declares its media type as application/vnd.dev.sigstore.bundle+json. Look at the file your pipeline downloads:

jq 'keys' artifact.bundle.json
jq -r '.mediaType // "no mediaType (likely legacy)"' artifact.bundle.json

Downloaded bundles are attacker-influenced input in exactly the case this advisory describes, so inspect them before trusting any pipeline that fetches a bundle from the same place as the artifact.

What to do now

  1. Upgrade Cosign to v3.1.3, or v2.6.5 if you are still on the v2 line. Pin the version in your install step.
  2. If you install Cosign in GitHub Actions or another CI system, pin the installer by commit or checksum, not a moving tag.
  3. Move blob signatures to the protobuf bundle format. The advisory names this as the workaround, and cosign bundle create accepts an old format bundle and writes a new one:
cosign bundle create --bundle old.bundle.json --artifact release.tar.gz --out release.sigstore.json

Check the help output of cosign bundle create for the exact flags your installed version expects.

  1. Re-verify with explicit identity and issuer, using the form shown in the Sigstore docs:
cosign verify-blob release.tar.gz --bundle release.sigstore.json \
  --certificate-identity=name@example.com \
  --certificate-oidc-issuer=https://accounts.example.com
  1. Re-run verification for artifacts you consumed during the exposure window if the bundle came from a source you do not control.

The release notes for v3.1.2 also say that release may be the last v3.1 version before work on Cosign v4, and encourage moving to the bundle format supported since v2.6. Treat that as the migration signal.

How this could have been avoided

  • Use the protobuf bundle format. The advisory says its verification engine is not affected. Teams that had already migrated were never exposed.
  • Pin both identity and issuer, then test that the pin bites. Add a negative test to CI: verify a known artifact with a wrong identity and require a non-zero exit code. A bypass of this kind turns that test red.
  • Keep your verifier current. A version check in CI that fails when Cosign is older than your minimum catches this class quickly.
  • Verify by digest, from a location you control. Do not fetch the artifact and its bundle from the same unauthenticated place and trust whatever arrives.
  • Log the identity and issuer you enforced. A wrapper script that prints both makes a missing assertion visible in review.

Why it matters

Signature verification is a security control, and controls need tests like any other code. This bug was not a broken algorithm. It was a fallback path that treated a parse failure as permission to try a weaker mode.

The failure mode is also worth remembering for your own tooling: when a strict check cannot run, fail closed and say why. A tool that quietly downgrades is worse than one that errors.

Try it yourself

Write a small script that runs your real verify command once with the correct identity and once with a deliberately wrong one, and fail the build unless the first passes and the second fails. Run it on every Cosign upgrade. Then see how build provenance and attestations fit together.

Click through it at your own pace, or open it full screen.

Quick check

Is cosign verify on a container image affected by this advisory?

No. The advisory lists container image verification with cosign verify and cosign verify-attestation as not affected. The issue is in blob and blob attestation verification with legacy JSON bundles.

Which versions contain the fix?

Cosign v3.1.3 and v2.6.5.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.