CVEReports
CVEReports

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

Product

  • Home
  • Dashboard
  • 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-22772
5.80.01%

The Unanchored Trust: Bypassing Fulcio's OIDC Validation (CVE-2026-22772)

Alon Barad
Alon Barad
Software Engineer

Feb 20, 2026·5 min read·6 visits

PoC Available

Executive Summary (TL;DR)

Fulcio failed to anchor regular expressions (`^...$`) when validating OIDC issuer URLs containing wildcards. This allowed attackers to craft malicious URLs that merely *contained* a trusted substring, fooling Fulcio into making HTTP requests to attacker-controlled or internal endpoints (SSRF). Fixed in version 1.8.5.

A classic regular expression oversight in Sigstore Fulcio's MetaIssuer validation allowed attackers to bypass domain allowlists. By embedding trusted domain strings into malicious URLs, attackers could trigger Server-Side Request Forgery (SSRF) via the OpenID Connect discovery process, potentially exposing internal cloud metadata.

The Hook: Trust, but Verify (Poorly)

Sigstore Fulcio is effectively the bouncer of the modern software supply chain. Its job is to issue short-lived code signing certificates based on OpenID Connect (OIDC) identities. If you can prove you own alice@example.com via Google login, Fulcio gives you a cert. To make this work at scale—especially for dynamic cloud environments like AWS EKS or GCP—Fulcio introduced "MetaIssuers."

Instead of hardcoding every single cluster ID, administrators could define patterns with wildcards, like https://oidc.eks.*.amazonaws.com/id/*. It sounds convenient, a classic ease-of-use feature. But as any security researcher knows, whenever a developer tries to convert a wildcard string into a Regular Expression dynamically, a vulnerability is born. The old adage holds true: "Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems."

In this case, the second problem was CVE-2026-22772. The logic used to validate these issuers had a gaping hole—it forgot to check where the string started and ended. It's the digital equivalent of a bouncer checking a fake ID, seeing "McLovin" written in crayon on the back of a napkin, and saying, "Close enough, come on in."

The Flaw: The Anchor Management Issue

The vulnerability lies in how Fulcio's pkg/config/config.go handled the MetaRegex generation. When an administrator configured a pattern with a wildcard *, the code helpfully converted that * into a regex character class [-_a-zA-Z0-9]+. So far, so good.

However, in Go's regexp package (and many others), functions like MatchString search for the pattern anywhere inside the target string unless you explicitly tell them not to. If your regex is abc and the input is xyz_abc_123, it returns true. This is a substring match, not an exact match.

Because the generated regex lacked the start-of-line (^) and end-of-line ($) anchors, the validation logic didn't enforce that the entire URL match the trusted pattern. It only checked if the trusted pattern appeared somewhere inside the URL provided by the user. This effectively turned a strict allowlist into a "does it mention the secret password?" check.

The Code: The Smoking Gun

Let's look at the diff. It is painfully simple, yet it highlights how subtle regex bugs can be. The vulnerable code took the configuration string, quoted the meta-characters, swapped the wildcards, and compiled it.

Here is the fix from commit eaae2f2be56df9dea5f9b439ec81bedae4c0978d:

// pkg/config/config.go
 
func MetaRegex(issuer string) (*regexp.Regexp, error) {
    // 1. Escape the input string to treat dots/slashes as literals
    quoted := regexp.QuoteMeta(issuer)
    
    // 2. Replace the escaped wildcard with a character set
    replaced := strings.ReplaceAll(quoted, regexp.QuoteMeta("*"), "[-_a-zA-Z0-9]+")
 
    // THE FIX: Explicitly anchor the regex to start (^) and end ($)
    // Vulnerable version was missing this line:
    replaced = "^" + replaced + "$"
 
    return regexp.Compile(replaced)
}

Without the ^ and $, a pattern intended to match https://trusted.com would also match http://attacker.com/exploit?padding=https://trusted.com.

The Exploit: Smuggling the Issuer

To exploit this, we need to bypass the validation check and force Fulcio to make an outgoing HTTP request to a destination of our choice. This is a classic Server-Side Request Forgery (SSRF).

The Setup: Assume Fulcio is configured to trust https://oidc.eks.us-west-2.amazonaws.com/id/*.

The Attack Chain:

  1. Crafting the Payload: The attacker sets up a malicious OIDC provider or a simple HTTP server at http://attacker.com.
  2. The Smuggle: The attacker creates a JWT with an iss (Issuer) claim that looks like this:
    http://attacker.com/foo?bypass=https://oidc.eks.us-west-2.amazonaws.com/id/123
  3. The Check: Fulcio receives the request. It runs the regex against the iss claim. Because the regex is unanchored, it finds the valid AWS string inside the query parameter. Validation passes.
  4. The Fetch: Fulcio, believing this is a valid issuer, appends /.well-known/openid-configuration to the attacker's URL and performs a GET request.
  5. The Pivot: The attacker's server receives the request. Now, the attacker can respond with a 302 Redirect to an internal IP, or simply serve a JSON document pointing the jwks_uri to a sensitive internal location.

The Impact: Why Should We Panic?

This is a Blind SSRF. Fulcio generally won't return the body of the jwks_uri response to the user in the certificate itself. However, in cloud environments, SSRF is often the first step in a "Cloud Break."

If Fulcio is running on AWS EC2, and the attacker points the jwks_uri to http://169.254.169.254/latest/meta-data/iam/security-credentials/, Fulcio will fetch those credentials. While the attacker doesn't see them immediately, they might be leaked if:

  1. Fulcio logs the error message containing the response body (common in debug logs).
  2. The attacker can measure timing differences to map internal network topology.

Even without data exfiltration, an attacker can map the internal network, identifying which ports are open on localhost or adjacent services.

The Fix: Anchors Aweigh

The remediation is straightforward: Update to Fulcio v1.8.5.

If you cannot update immediately, your only mitigation is to disable wildcards in your MetaIssuer configuration. Use exact, full URL matches for your OIDC issuers. If you don't use wildcards, the vulnerable MetaRegex function is likely not invoked in the same hazardous way (or you can rely on static issuer lists).

For developers reading this: this is your reminder that MatchString is not FullMatch. If you are validating security boundaries with Regex, always wrap your pattern in ^ and $.

Official Patches

SigstoreOfficial Release v1.8.5

Fix Analysis (1)

Technical Appendix

CVSS Score
5.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N
EPSS Probability
0.01%
Top 99% most exploited

Affected Systems

Sigstore Fulcio < 1.8.5

Affected Versions Detail

Product
Affected Versions
Fixed Version
Fulcio
Sigstore
< 1.8.51.8.5
AttributeDetail
Attack VectorNetwork (SSRF)
CVSS v3.15.8 (Medium)
CWECWE-918 (Server-Side Request Forgery)
Exploit StatusProof of Concept
EPSS Score0.00009
Patch Commiteaae2f2be56df9dea5f9b439ec81bedae4c0978d

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1552Unsecured Credentials
Credential Access
CWE-918
Server-Side Request Forgery (SSRF)

The software does not properly validate that the input matches the entire regular expression, allowing for substring matches that bypass security checks.

Known Exploits & Detection

Internal ResearchPoC involves appending a trusted issuer string as a query parameter to a malicious domain.

Vulnerability Timeline

CVE Published
2026-01-12
Patch Released (v1.8.5)
2026-01-12

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Record

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.