CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-22703
5.50.01%

Broken Ledger: Bypassing Sigstore Cosign's Transparency (CVE-2026-22703)

Alon Barad
Alon Barad
Software Engineer

Feb 20, 2026·7 min read·13 visits

PoC Available

Executive Summary (TL;DR)

Cosign forgot to check if the ID card belonged to the person holding it. A logic flaw in the verification code allowed an attacker to present a valid transparency log entry for a benign file while actually delivering a malicious one, tricking the system into marking the malware as 'verified' and 'logged'.

A deep dive into a logic regression in Sigstore Cosign that broke the fundamental promise of transparency logs. By exploiting an early return in the verification routine, attackers could bind a valid Rekor log entry for one artifact to a completely different, malicious artifact, effectively bypassing the 'proof of inclusion' check.

The Hook: The Transparency Illusion

Supply chain security is built on a simple premise: Trust, but verify. Sigstore changed the game by adding a third pillar: Log everything. The idea is that if I sign a binary, that event is recorded in Rekor (the transparency log). When you verify my binary, you don't just check my signature; you check the log to prove I publicly announced this release. It's the digital equivalent of a notary public stamping a document in a book that everyone can see.

But what happens when the notary checks the stamp but forgets to read the document? That is exactly what happened in CVE-2026-22703. For a specific set of configurations involving 'Trusted Roots' (which, ironically, are the more secure way to configure Sigstore), Cosign stopped acting like a strict border guard and started acting like a tired club bouncer who just glances at the ID without looking at the face.

This vulnerability is a 'binding bypass.' In cryptography, binding is everything. A signature must be bound to a message. A certificate must be bound to an identity. A transparency log entry must be bound to the specific artifact it represents. CVE-2026-22703 severed that last link, allowing an attacker to perform a digital bait-and-switch that renders the transparency log—the core feature of the ecosystem—useless for validation.

The Flaw: Premature Optimization's Ugly Cousin

The root cause of this vulnerability isn't a buffer overflow or a complex heap grooming technique. It is the silent killer of logic: the Early Return. In software engineering, we often use early returns (guard clauses) to clean up code. 'If input is null, return error.' But in security-critical code, flow control is everything. If you return 'Success' too early, you skip the rest of the exam.

The vulnerability resides in pkg/cosign/verify.go, specifically within the VerifyBundle function. This function has two jobs: verify the Rekor entry's signature (authenticity) and ensure the Rekor entry matches the artifact (binding). The regression was introduced when handling TrustedMaterial—a newer abstraction for managing root keys.

When TrustedMaterial was present, the code successfully verified that the Rekor entry was signed by the Rekor service. It validated the timestamp and the TLOG signature. And then... it just stopped. It returned nil (no error). It completely skipped the subsequent lines of code responsible for calling compareSigs, comparePublicKey, and verifying the bundleHash against the payloadHash. It verified the container, but ignored the contents.

The Code: The Smoking Gun

Let's look at the logic flow to understand how egregious this skip was. The vulnerable code effectively did this:

// Vulnerable Logic (Conceptual)
func VerifyBundle(ctx, bundle, trustedMaterial, artifact) error {
    // Step 1: Check if the log entry is signed by Rekor
    if trustedMaterial != nil {
        // Check the Signed Entry Timestamp (SET)
        if err := verifySET(bundle, trustedMaterial); err != nil {
            return err
        }
        // OOPS: We return here! Success!
        return nil
    }
 
    // ...
    // The code below this line is what actually checks if the bundle 
    // belongs to the artifact. It is unreachable if trustedMaterial != nil.
    // ...
    
    if !compareSigs(bundle, artifact) { return Error }
    if !verifyHash(bundle, artifact) { return Error }
    return nil
}

The patch acts as a harsh corrective measure, hoisting the binding checks to the very top of the function. This ensures that no matter what configuration flags are passed or what new features are added later, the fundamental identity check happens first.

// Patched Logic (Conceptual)
func VerifyBundle(ctx, bundle, trustedMaterial, artifact) error {
    // FIX: Verify the binding IMMEDIATELY.
    // Does the log entry actually talk about THIS artifact?
    if !compareSigs(bundle, artifact) { return Error }
    if !verifyHash(bundle, artifact) { return Error }
 
    // Now we can worry about who signed the log entry
    if trustedMaterial != nil {
        return verifySET(bundle, trustedMaterial)
    }
    // ...
}

By moving the binding verification before the trusted material check, the developers closed the loop. It’s a textbook example of why 'fail-safe defaults' and 'defense in depth' are difficult to maintain as codebases grow and refactor.

The Exploit: The Old Switcheroo

To exploit this, we don't need to crack the Rekor private key. We just need to be a lawful user of the system who decides to break the rules. The attack is a Substitution Attack. Here is how a malicious actor, let's call him 'Mallory', pulls this off.

First, Mallory compiles a benign application, hello-world.bin. He signs it with his valid key and submits it to the Rekor transparency log. Rekor responds with a bundle: a signed entry saying 'I, Rekor, witness that Mallory signed hash X at time T.'

Next, Mallory compiles his malware, ransomware.bin. He signs this malware with his same valid key. Now he has a valid signature for the malware. But if he uploads this to Rekor, security researchers might spot it in the public log. So, he doesn't upload it.

Instead, Mallory creates a Frankenstein bundle. He takes the signature from the malware, but he attaches the Rekor bundle from the benign application.

When the victim runs cosign verify --trusted-root=... ransomware.bin, Cosign looks at the bundle. It sees a valid signature on the binary (from Mallory). It then checks the Rekor entry. It asks, 'Is this a valid Rekor entry?' Yes, it is (it's the entry for hello-world.bin). Because of the bug, Cosign stops there. It never asks, 'Does this Rekor entry hash match the ransomware.bin hash?'

The victim installs the ransomware, believing it was properly logged and vetted in the transparency system.

The Impact: Trust Erosion

The CVSS score of 5.5 (Medium) feels deceptively low here, likely dragged down by the complexity of the required configuration (specifically using TrustedMaterial roots) and the requirement for the attacker to have a valid signing key (or a compromised one). However, the implication is severe.

The entire value proposition of Sigstore is that it makes software supply chains observable. If you can bypass the log verification, you turn Sigstore back into a standard PKI system, stripping away the 'transparency' protection against key compromise. If a developer's key is stolen, the attacker can sign malware and hide it from the public log by reusing old, valid log entries. The public audit trail—the mechanism designed to catch exactly this scenario—becomes blind to the attack.

For organizations relying on Cosign policy controllers in Kubernetes (e.g., ensuring all pods are logged in Rekor), this bypass means untracked images could be deployed into production environments while appearing fully compliant.

The Fix: Trust, Verify, Then Verify Again

The remediation is straightforward: Update Cosign. The patch is available in versions 2.6.2 and 3.0.4. If you are running a vulnerable version, you are flying blind.

If you cannot update immediately, there is a configuration-based workaround. The vulnerability is triggered specifically when using the modern TrustedMaterial path (often invoked via --trusted-root or TUF). If you manually specify the Rekor public key using the legacy method, you can force the code into the older execution path which—ironically—did not have this bug.

> [!TIP] > Workaround: Set the SIGSTORE_REKOR_PUBLIC_KEY environment variable to the path of the Rekor public key. This bypasses the TrustedMaterial logic branch entirely in the affected versions.

Ultimately, this is a lesson in code paths. When refactoring for new features (like TUF support), legacy verification logic must be rigorously audited to ensure 'obvious' checks aren't implicitly dropped.

Official Patches

SigstoreRelease v2.6.2
SigstoreRelease v3.0.4

Fix Analysis (2)

Technical Appendix

CVSS Score
5.5/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
EPSS Probability
0.01%
Top 100% most exploited

Affected Systems

Sigstore Cosign < 2.6.2Sigstore Cosign 3.0.0 - 3.0.3

Affected Versions Detail

Product
Affected Versions
Fixed Version
sigstore/cosign
Sigstore
< 2.6.22.6.2
sigstore/cosign
Sigstore
>= 3.0.0, < 3.0.43.0.4
AttributeDetail
CWECWE-345 (Insufficient Verification of Data Authenticity)
CVSS v3.15.5 (Medium)
Attack VectorLocal / Context-Dependent
ImpactIntegrity Bypass / Supply Chain Poisoning
Exploit StatusPoC Available (Theoretical)
GHSA IDGHSA-whqx-f9j3-ch6m

MITRE ATT&CK Mapping

T1553.002Subvert Trust Controls: Code Signing
Defense Evasion
T1195.002Supply Chain Compromise: Compromise Software Supply Chain
Initial Access
CWE-345
Insufficient Verification of Data Authenticity

The software does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data.

Known Exploits & Detection

GitHub AdvisoryProof of concept outlined in the advisory involving substitution of Rekor entries.
NucleiDetection Template Available

Vulnerability Timeline

Fixes merged into main branch
2026-01-09
Advisory Published
2026-01-10

References & Sources

  • [1]GHSA-whqx-f9j3-ch6m
  • [2]NVD CVE-2026-22703

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.