CVE-2026-29000: The CVSS 10.0 pac4j-jwt Authentication Bypass That Lets Anyone Become Admin


Executive Summary

CVE-2026-29000 is a critical authentication bypass vulnerability in the pac4j-jwt library — a widely used Java security component for JWT authentication. It carries a CVSS score of 10.0 across both CVSS 3.1 and CVSS 4.0 scoring systems, placing it in the most severe possible vulnerability tier. The flaw requires no authentication, no user interaction, and works entirely over the network. An attacker needs only the server’s RSA public key — information that is typically published in JWKS endpoints, embedded in configurations, or derivable from TLS certificates — to forge arbitrary authentication tokens and impersonate any user, including administrators.

Discovered by CodeAnt AI’s automated code review platform and coordinated with the pac4j maintainers, this vulnerability represents a textbook case of confusing encryption with authentication: the library treated a successfully decrypted JWE envelope as proof of authenticity, when in reality RSA public keys are designed to be public. NVD Entry for CVE-2026-29000

Metric Value
CVE ID CVE-2026-29000
CVSS Score 10.0 (Critical)
CVSS Vector (3.1) CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L
CVSS Vector (4.0) CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L
CWE CWE-347 (Improper Verification of Cryptographic Signature)
Discovered March 4, 2026
Vendor pac4j / org.pac4j
Affected Artifact org.pac4j:pac4j-jwt

CVE Details

The vulnerability lives in the JwtAuthenticator class of pac4j-jwt, which handles the validation of incoming JWT tokens. The library uses com.nimbusds:nimbus-jose-jwt as its underlying JWT parsing engine. All versions prior to the following patched releases are affected:

Branch Patched Version
4.x 4.5.9
5.x 5.7.9
6.x 6.3.3

The vulnerability is classified under CWE-347: Improper Verification of Cryptographic Signature, and maps to MITRE ATT&CK Tactic: Initial Access (TA0001), Technique: Exploit Public-Facing Application (T1190). CIS Advisory 2026-019

CVSS Breakdown

Every metric in the CVSS 3.1 vector reveals why this vulnerability scores 10.0:

Metric Value Meaning
Attack Vector (AV) Network 🔴 Exploitable remotely over the internet — no physical or local network access needed
Attack Complexity (AC) Low 🔴 No special conditions, race windows, or timing constraints. The exploit is straightforward to execute
Privileges Required (PR) None 🔴 The attacker needs no login, no API key, no session — just network access to the authentication endpoint
User Interaction (UI) None 🔴 No victim needs to click a link, open a file, or perform any action. The attack is fully automated
Scope (S) Changed 🔴 The vulnerable component (JWT validation library) runs inside a larger application. Compromising auth affects the whole app
Confidentiality (C) High 🔴 An attacker gains the privileges of any user including admin — full read access to all protected data
Integrity (I) High 🔴 The attacker can modify, delete, or impersonate within the application at any privilege level
Availability (A) Low 🟡 The primary impact is on authentication integrity, not service availability, though admin-level access could disrupt operations

Affected Systems

pac4j is the authentication engine behind many Java frameworks and deployments:

  • Spring Security applications with pac4j integration
  • CAS (Central Authentication Service) servers — widely deployed in universities and government institutions
  • Play Framework applications using pac4j-jwt
  • Vert.x applications with pac4j authentication
  • JEE applications using pac4j as auth provider
  • Any custom Java app including org.pac4j:pac4j-jwt as a dependency

The service surface for this vulnerability is any HTTP(S) endpoint that accepts JWT bearer tokens for authentication. This typically includes:

  • Login/logon endpoints
  • API gateway authentication filters
  • Microservice-to-microservice auth tokens
  • Single sign-on (SSO) assertion endpoints

Root Cause

The vulnerability stems from a fundamental confusion between encryption (confidentiality) and digital signatures (authenticity). The JWT ecosystem defines two distinct token types:

  1. JWS (JSON Web Signature) — A signed token. The signature cryptographically proves the token was issued by a trusted party and hasn’t been tampered with.
  2. JWE (JSON Web Encryption) — An encrypted token. Encryption protects the contents from being read, but does not prove who created the token.

When pac4j’s JwtAuthenticator receives an encrypted JWT (JWE), it follows this process:

  1. Decrypt the outer JWE envelope using the server’s RSA private key
  2. Parse the inner payload
  3. Verify the signature on the inner token

The flaw is in step 3. After successful JWE decryption, the library calls toSignedJWT() in nimbus-jose-jwt on the inner payload. If the inner payload is a PlainJWT (an unsigned JWT with alg: none), toSignedJWT() returns null. In the vulnerable code, this null caused the entire signature verification block to be skipped — the library effectively treated a null return as “no signature to verify, let’s move on.” Snyk — How a Public Key Breaks Authentication in pac4j-jwt

The simplified vulnerable logic:

// After JWE decryption succeeds above
SignedJWT signedJWT = encryptedJWT.getPayload().toSignedJWT();

// If inner token is PlainJWT, signedJWT is null
if (signedJWT != null) {
    jwt = signedJWT;
}

// Signature verification only runs if signedJWT is not null
if (signedJWT != null && !signatureConfigurations.isEmpty()) {
    // Verify signature... but this block is NEVER entered
    // for a PlainJWT wrapped in JWE
}

// Claims are extracted regardless — attacker is now "authenticated"
createJwtProfile(ctx, credentials, jwt);

The fix added an explicit rejection: when the inner token is not a SignedJWT, the authenticator now throws an exception rather than silently accepting the claims. GitHub Advisory GHSA-pm7g-w2cf-q238

Exploit Analysis

Attack Surface

Any public-facing authentication endpoint that accepts JWT bearer tokens in the Authorization header is exploitable. The attack surface is network-wide: no prior access to the target is needed beyond the ability to send HTTP requests.

Exploitation Mechanics

The attack requires just two things: a target server’s RSA public key and network access.

Step 1: Obtain the RSA public key. The attacker finds the public key through standard discovery mechanisms:

  • JWKS endpoint — Many Java apps expose /.well-known/jwks.json or /oauth/jwks
  • Application configuration — Public keys embedded in open-source configs or client-side code
  • TLS certificate analysis — RSA key pairs used in TLS can sometimes be correlated
  • Public repositories — Accidental inclusion in public GitHub repos (a common finding in CodeAnt’s own research)

Step 2: Forge the token. The attacker:

  1. Creates a PlainJWT (unsigned JWT with alg: none header) containing arbitrary claims — e.g., {"sub": "admin", "role": "administrator"}
  2. Wraps this PlainJWT inside a JWE envelope encrypted with the target server’s RSA public key
  3. Sends the forged JWE token as the Authorization: Bearer <token> header

Step 3: Bypass authentication. The target server:

  1. Decrypts the JWE using its RSA private key
  2. Unwraps the PlainJWT payload
  3. Calls toSignedJWT() which returns null (PlainJWT has no signature)
  4. Skips signature verification because the result was null
  5. Extracts the arbitrary claims and authenticates the attacker as admin

Step 4: Profit. The attacker now has whatever access the application grants to the impersonated role — data exfiltration, privilege escalation, lateral movement, or persistence.

Wormability Assessment

This vulnerability has low wormability because each forged token is bound to a specific server’s public key. An attacker cannot reuse a forged token from one server to compromise another server with a different RSA key pair. However, the attack is highly automatable: scripts can scan for JWKS endpoints, extract public keys, forge tokens, and attempt authentication — all without any manual intervention.

A public proof-of-concept was released by CodeAnt AI shortly after the coordinated disclosure. CodeAnt AI Security Research

Detection

Indicators of Compromise

Indicator Description
JWT tokens with alg: none Presence of unsigned JWT headers inside JWE envelopes in authentication logs
Privileged logins from unusual IPs Successful admin-level authentication events originating from unexpected geographies
Missing signature values JWT tokens that decrypt successfully but contain no jku, jwk, kid, or sig fields
Bulk authentication attempts High volume of token submissions targeting auth endpoints in short windows
JWKS endpoint scans Unusual access patterns to /.well-known/jwks.json or similar discovery endpoints

Detection Strategies

Log-Level Detection — Enable verbose logging on JWT authentication components to capture full token processing details. Log the JWT algorithm type (JWE header alg and enc) for every authentication attempt. Flag tokens using alg: none or containing PlainJWT structures.

Network-Level Detection — Deploy WAF rules that inspect JWT structures before they reach the application backend. Many WAFs can detect and block JWT tokens with alg: none headers.

SIEM Query Patterns

// Sentinel/Azure Log Analytics query:
AuthenticationLogs
| where Timestamp > ago(7d)
| where AuthenticationResult == "Success"
| where UserPrincipalName contains "admin"
| where ClientIP !in (known_admin_networks)
| extend Algorithm = extractjson("$.header.alg", RawToken)
| where Algorithm == "none" or isempty(Algorithm)

Behavioral Detection — Monitor for sudden privilege escalation patterns where a standard user account authenticates and immediately performs administrative actions. This anomaly is common in forged-token attacks.

Monitoring Recommendations

  • Set up alerts for authentication attempts using encrypted (JWE) tokens from external or untrusted IP ranges
  • Monitor RSA public key access patterns and downloads from JWKS endpoints — sudden spikes may indicate reconnaissance
  • Track toSignedJWT() return values in application logs (with appropriate performance considerations)
  • Implement token fingerprinting to detect tokens not issued by your authorization server

Mitigation

Immediate Patching

Upgrade to a patched version immediately:

  • 4.x branch: Upgrade to 4.5.9 or later
  • 5.x branch: Upgrade to 5.7.9 or later
  • 6.x branch: Upgrade to 6.3.3 or later

For Maven projects, update your pom.xml:

<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>pac4j-jwt</artifactId>
    <version>6.3.3</version>
</dependency>

Pac4j Security Advisory

Additional Hardening

  • Token validation middleware — Implement a pre-validation filter that explicitly rejects tokens with alg: none or PlainJWT structures before they reach the authenticator
  • Audit and rotate — Audit all existing authentication sessions, invalidate tokens that may have been forged, and force re-authentication for all users
  • Defense in depth — Add application-layer authorization checks beyond JWT validation. Do not rely solely on token claims for privilege decisions
  • JWKS endpoint lockdown — If your JWKS endpoint does not need to be public, restrict access to known consumers via IP allowlisting or mutual TLS
  • Cryptographic agility — Consider using asymmetric keys specifically for JWT signing (RS256/ES256) that are distinct from TLS key pairs, reducing the surface area for key discovery

Inventory Checklist

  • Identify all applications using org.pac4j:pac4j-jwt
  • Check current version via mvn dependency:tree | grep pac4j-jwt
  • Verify patched version on all instances (dev, staging, prod)
  • Rotate authentication tokens and force re-login for all users
  • Review authentication logs for the past 30 days for IOC matches
  • Check JWKS endpoint access logs for anomalous patterns
  • Run a penetration test targeting JWT authentication endpoints

Workarounds (if immediate patching is not possible)

If upgrading is not immediately feasible, configure JwtAuthenticator to reject tokens with alg: none at the application level:

// Example workaround filter
public class NoNoneAlgorithmFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        String authHeader = ((HttpServletRequest) req).getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            // Decode JWT header (first base64 segment)
            String header = new String(Base64.getUrlDecoder().decode(
                token.split("\\.")[0]
            ));
            if (header.contains("\"alg\":\"none\"") || header.contains("\"alg\": \"none\"")) {
                ((HttpServletResponse) res).setStatus(401);
                return;
            }
        }
        chain.doFilter(req, res);
    }
}

Note: This is a stopgap, not a substitute for patching. Sophisticated attackers may encode the alg field in unexpected ways.

Timeline

Date Event
2026-02-20 CodeAnt AI’s automated code review discovers the flaw in pac4j-jwt
2026-02-20 Coordinated disclosure to pac4j maintainers
2026-03-04 CVE published; NVD entry created
2026-03-04 Patched versions 4.5.9, 5.7.9, 6.3.3 released
2026-03-05 GitHub Advisory GHSA-pm7g-w2cf-q238 published
2026-03-05 CIS MS-ISAC issues advisory 2026-019
2026-03-06 Public PoC released by CodeAnt AI
2026-07-11 This analysis published

Implications

Risk Tiers

Deployment Type Risk Level Rationale
Internet-facing with JWT auth Critical 🔴 Publicly accessible auth endpoints, JWKS often exposed
Internal CAS/SSO servers High 🟠 Compromise gives lateral movement across org
Microservice mesh with JWT High 🟠 Service-to-service auth bypass enables east-west movement
Offline/internal only apps Medium 🟡 Reduced exposure, but internal attackers still a threat

The EPSS (Exploit Prediction Scoring System) probability for this vulnerability is 0.24% as of July 2026 NVD Entry for CVE-2026-29000 — meaning the exploitation-in-the-wild probability remains low, likely because the vulnerability targets Java backend infrastructure rather than end-user devices. However, the CVSS 10.0 score and the availability of public PoC code mean that targeted attacks against high-value Java-backed organizations are a realistic threat. Automated scanning for vulnerable JWT endpoints via JWKS discovery is straightforward and likely already happening at scale.

This vulnerability is especially dangerous because it subverts the fundamental trust model of encrypted JWTs: the assumption that a token you can decrypt must be authentic. That assumption is what led to the null-check logic flaw. In the words of the Snyk analysis, “the flaw is both devastating and conceptually simple.” Snyk Analysis

Recommendations

  1. Patch now. This is a CVSS 10.0 vulnerability with public exploit code. If you run pac4j-jwt, this should be your highest-priority remediation this week.
  2. Audit authentication logs. Look for tokens with missing alg headers, successful admin logins from unusual sources, or bulk JWKS endpoint access.
  3. Implement detection rules. Add WAF rules and log monitoring for alg: none JWT tokens and PlainJWT structures.
  4. Force session rotation. Invalidate all existing tokens and require re-authentication after patching.
  5. Review disclosure practices. CodeAnt AI’s discovery of this flaw through automated code review highlights the growing role of AI-powered SAST in catching subtle logic flaws that traditional scanners miss. Review whether your CI/CD pipeline includes automated SAST that can detect CWE-347 patterns.
  6. Adopt cryptographic best practices. Use distinct key pairs for signing vs. encryption. Avoid publishing RSA public keys in easily discoverable locations unless required by your protocol.

Sources

  1. NVD — CVE-2026-29000 Detail
  2. GitHub Advisory — GHSA-pm7g-w2cf-q238
  3. Snyk — How a Public Key Breaks Authentication in pac4j-jwt
  4. SentinelOne Vulnerability Database — CVE-2026-29000
  5. CIS Advisory 2026-019
  6. Pac4j Security Advisory
  7. CodeAnt AI Security Research
  8. VulnCheck Advisory
  9. Reddit r/cybersecurity — PSA Discussion
  10. Check Point Research — CVSS 10.0 Analysis