CVE-2026-22772

CVE-2026-22772: Unanchored Trust in Sigstore Fulcio

Alon Barad
Alon Barad
Software Engineer

Jan 13, 2026·6 min read

Executive Summary (TL;DR)

Fulcio uses regular expressions to validate trusted OIDC providers via 'MetaIssuers'. The generated regexes were missing start and end anchors ('^' and '$'). This allows an attacker to embed a trusted domain string anywhere in a malicious URL (e.g., as a query parameter) to bypass validation and force Fulcio to connect to arbitrary internal or external hosts.

A classic regex implementation failure in Sigstore Fulcio allows attackers to bypass OIDC issuer whitelists, leading to Blind Server-Side Request Forgery (SSRF).

The Hook: Trust Without Anchors

Sigstore Fulcio is the shiny new toy in the software supply chain security world. It acts as a Root CA that issues short-lived code-signing certificates based on OIDC identities. In plain English: you log in with Google, GitHub, or Microsoft, and Fulcio gives you a certificate that says, "Yes, this person signed this code."

To make this work, Fulcio needs to talk to OIDC providers (Issuers) to verify tokens and fetch public keys. Because letting a CA talk to just any server on the internet is a bad idea, Fulcio allows administrators to define a whitelist of trusted issuers using the MetaIssuers configuration. This supports wildcards, so an admin can say "Trust anything looking like https://oidc.eks.*.amazonaws.com".

It sounds secure on paper. But as with most things in security, the devil is in the implementation details—specifically, in how we translate human intent (wildcards) into machine logic (regular expressions). CVE-2026-22772 is the story of what happens when you build a security gate but forget to put a wall around it.

The Flaw: Regex is a Footgun

The vulnerability lies in the metaRegex function within pkg/config/config.go. The goal of this function is simple: take a configuration string like https://issuer.example.com/* and turn it into a Go regular expression that the server can use to validate incoming Issuer URLs.

The logic was straightforward: escape the special characters and replace the wildcard * with a character class [-_a-zA-Z0-9]+. However, the developers missed the most common pitfall in regex generation: anchoring.

In Go (and many other languages), regexp.MatchString checks if the pattern exists anywhere inside the target string. It does not enforce that the pattern matches the entire string unless you explicitly tell it to using ^ (start of string) and $ (end of string). Without these anchors, the validation logic effectively became: "Does this URL contain the trusted domain?" rather than "Is this URL the trusted domain?"

The Code: Autopsy of a Bad Regex

Let's look at the smoking gun. This is the code responsible for generating the validator regex before the patch. It takes the administrator's input and compiles it directly.

// Vulnerable Code in pkg/config/config.go
func metaRegex(issuer string) (*regexp.Regexp, error) {
    // 1. Escape the input so dots aren't regex wildcards
    quoted := regexp.QuoteMeta(issuer)
    // 2. Replace the user's * with a regex character class
    replaced := strings.ReplaceAll(quoted, regexp.QuoteMeta("*"), "[-_a-zA-Z0-9]+")
    
    // 3. THE BUG: Compiling without ^ and $
    return regexp.Compile(replaced)
}

If an admin configured https://trusted.com, the resulting regex was literally https://trusted\.com. If an attacker submits http://evil.com/?ignore=https://trusted.com, the regex engine sees the match in the query parameter and returns true. The validation passes, and Fulcio proceeds to connect to http://evil.com.

The fix was painfully simple. They just had to force the regex to match the full string boundary:

- return regexp.Compile(replaced)
+ replaced = "^" + replaced + "$"
+ return regexp.Compile(replaced)

The Exploit: Surfing the Substring

To exploit this, we need to trick Fulcio into making an HTTP request to a server we control (or an internal IP), while convincing the validator that we are a trusted OIDC provider. Let's assume the admin trusts https://oidc.eks.us-east-1.amazonaws.com/id/*.

Step 1: The Setup We set up a malicious server at attacker.com. We also need to craft a URL that satisfies the unanchored regex. We can simply append the trusted domain as a query parameter or a path fragment that gets ignored by our server.

Step 2: The Trigger We send a certificate request to Fulcio specifying our Issuer as: http://attacker.com/foo?bypass=https://oidc.eks.us-east-1.amazonaws.com/id/123

Fulcio's validator scans the string. It finds https://oidc.eks.us-east-1.amazonaws.com/id/123 inside the query parameter. The regex matches. Validation passes.

Step 3: The SSRF Fulcio now performs OIDC Discovery. It takes the entire URL (scheme and host included) and appends /.well-known/openid-configuration. It sends a GET request to: http://attacker.com/foo/.well-known/openid-configuration?bypass=...

Step 4: The Pivot Our malicious server responds with a valid JSON OIDC configuration, but we point the jwks_uri (where keys are stored) to a sensitive internal target.

{
  "issuer": "http://attacker.com...",
  "jwks_uri": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
}

Fulcio parses this and immediately tries to GET the jwks_uri. It connects to the AWS Metadata service. While Fulcio won't return the AWS keys to us (it expects a JSON Web Key Set, not IAM credentials), we have successfully forced the server to solicit sensitive internal data.

The Impact: Blind but Dangerous

This vulnerability is classified as Blind SSRF. Fulcio expects specific JSON formats (OIDC config and JWKS) in the response. If the internal service returns something else (like raw IAM strings or HTML), Fulcio will likely log an error and fail the certificate issuance. It won't conveniently echo the internal data back to the attacker in the HTTP response.

However, "Blind" does not mean "Harmless".

  1. Internal Port Scanning: Attackers can probe internal networks by timing how long requests take to fail. A quick RST packet vs. a timeout reveals infrastructure.
  2. Side Effects: Some internal APIs perform actions on GET requests (which is bad design, but common). An attacker could trigger these.
  3. WAF/Filter Bypass: Since the request originates from the trusted Fulcio server inside the network, it bypasses perimeter firewalls.

This is like a burglar who can't steal your TV, but can ring every doorbell in your house to see who's home.

The Fix: Dropping the Anchor

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

The patch explicitly anchors the regex, ensuring that the MetaIssuers pattern must match the entire provided URL, not just a part of it. If you cannot patch immediately, you are in a tough spot, as this is a logic flaw in the configuration parsing itself—there is no configuration workaround other than disabling MetaIssuers or being extremely restrictive with your network egress policies.

For developers reading this: this is your daily reminder that Matches usually means Contains. If you mean Equals, use ^...$. Always anchor your regexes unless you have a very specific reason not to.

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.02%
Top 97% most exploited

Affected Systems

Sigstore Fulcio < 1.8.5

Affected Versions Detail

Product
Affected Versions
Fixed Version
Sigstore Fulcio
Sigstore
< 1.8.51.8.5
AttributeDetail
CVE IDCVE-2026-22772
CWE IDCWE-918
CVSS Score5.8 (Medium)
Attack VectorNetwork
ImpactBlind SSRF / Information Disclosure
Exploit StatusPoC Available (Theoretical)
CWE-918
Server-Side Request Forgery (SSRF)

The application sends a request to a server that matches a regular expression, but the regular expression is not anchored, allowing the request to be sent to an arbitrary server if the trusted pattern appears anywhere in the URL.

Vulnerability Timeline

Vulnerability Published
2026-01-12
Patch Merged (v1.8.5)
2026-01-12
NVD Analysis
2026-01-13

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.