A critical authentication bypass in the pac4j-jwt library has been assigned a CVSS score of up to 10.0 and disclosed to the open source community. The vulnerability requires no stolen credentials, no brute force, and no insider access. An attacker who obtains a server's RSA public key — a key designed by definition to be shared — can forge a token that the system accepts as a fully authenticated identity, including administrator-level privileges.
CVE-2026-29000 was publicly disclosed on March 4, 2026, after being discovered and privately reported by the CodeAnt AI Security Research team. The vulnerability was confirmed by pac4j maintainer Jérôme Leleu, who patched it and published a formal security advisory crediting the research. On March 11, 2026, Sonatype expanded the known scope significantly, identifying 18 additional downstream packages beyond the originally reported pac4j-jwt component. As of that date, no in-the-wild exploitation had been confirmed — but the ease of exploitation and the breadth of affected software make this a situation that demands immediate attention across any Java environment relying on pac4j for authentication.
What pac4j Is and Why It Is Everywhere
pac4j is an open source Java security framework used to handle authentication and authorization across a wide range of protocols: OAuth, OpenID Connect, SAML, CAS, and JSON Web Tokens, among others. It is not a niche library. According to Sonatype's research, pac4j ranks among the top 2% of the most-downloaded components on Maven Central, with more than 30,000 vulnerable downloads recorded in the week immediately following disclosure.
The pac4j-jwt module specifically handles JWT-based authentication flows. It is commonly pulled in as a transitive dependency, meaning many development teams may not know it is present in their environment at all. When a Java application delegates its authentication logic to pac4j-jwt, it trusts the library to correctly verify that a token is legitimate before granting access. CVE-2026-29000 exploits the gap between what developers assume that verification does and what the code actually enforces.
The affected version ranges span three major release lines: everything in the 4.x line below 4.5.9, the 5.x line below 5.7.9, and the 6.x line below 6.3.3. The vulnerability was assigned CVE identifier CVE-2026-29000, published by VulnCheck on March 4, 2026, and classified under CWE-347: Improper Verification of Cryptographic Signature.
The Flaw: Encryption Is Not Authentication
To understand why this vulnerability exists, it helps to understand how JWT-based authentication is supposed to work when two security layers are combined. In many production pac4j deployments, tokens use a two-layer structure:
- Layer 1 — Encryption (JWE): The JWT is encrypted using the server's RSA public key. This protects the token's contents in transit. Only the server, which holds the corresponding private key, can decrypt it.
- Layer 2 — Signature (JWS): Inside the encrypted envelope, the JWT is signed by a trusted issuer. The server must verify this signature after decryption before trusting any identity claims.
Both layers must pass. Encryption only proves the server can read the message. It says nothing about who created it. Signature verification is the step that establishes trust in identity. In CVE-2026-29000, that second step can disappear entirely, silently, without generating any error.
NVD records a CVSS 3.1 base score of 9.1 Critical for this vulnerability. CodeAnt AI, the discovering team, assigned a CVSS score of 10.0 based on the completeness of the bypass. CISA's ADP enrichment of the CVE record, published March 7, 2026, classifies exploitation as "poc" (proof of concept publicly available), marks it as automatable, and assigns a technical impact of "total."
"OK. You're right. There is a critical security issue here." — Jérôme Leleu, pac4j maintainer, responding to CodeAnt AI's private disclosure, February 28, 2026. (CodeAnt AI Security Research)
How the Exploit Works, Step by Step
The root cause lives in JwtAuthenticator.java. When the authenticator receives an encrypted JWT (a JWE), it decrypts the outer envelope. It then attempts to parse the decrypted payload as a signed JWT by calling toSignedJWT() from the Nimbus JOSE+JWT library. If the inner payload is a properly signed token, this call returns a SignedJWT object. If the inner payload is a PlainJWT — an unsigned token — the call returns null.
The problem is what happens next. The entire signature verification block is gated behind a null check on signedJWT. When signedJWT is null, verification is silently skipped. The code then calls createJwtProfile(), which reads claims from the token and builds an authenticated user profile. Those claims are entirely attacker-controlled. No signature was ever checked. The server never confirmed the token was legitimate. But the user is now authenticated.
The attacker builds this token using only the server's RSA public key. That key is frequently available by design: published at a /.well-known/jwks.json endpoint, embedded in TLS certificates, or documented in the application's own configuration. No secret is required. No credential needs to be stolen. The attack is fully pre-authentication and, per CISA's assessment, automatable at scale.
pac4j-jwt versions prior to 4.5.9, 5.7.9, and 6.3.3 are vulnerable. If you are running any release in the 4.x line below 4.5.9, the 5.x line below 5.7.9, or the 6.x line below 6.3.3, you are exposed. Update immediately. Check for the artifact org.pac4j:pac4j-jwt in your dependency tree, including transitive pulls.
On March 8, 2026, security researcher Matthew Close independently reproduced the bypass and contributed an alternative proof-of-concept variant. Rather than nesting a PlainJWT, Close's variant delivers raw JSON claims directly as the JWE payload. CodeAnt AI noted in their updated disclosure that this simpler format provides an additional reproduction path across all three affected version lines. The underlying vulnerability, affected versions, and remediation remain unchanged — but the variant confirms the attack surface is not limited to a single payload structure.
Sonatype's Finding: 18 Additional Affected Packages
When Sonatype's Security Research team analyzed CVE-2026-29000, their findings diverged from the initial public advisory in two significant ways. First, they assigned a CVSS score of 9.1 rather than the 10.0 initially reported by CodeAnt AI, stating that their score more accurately reflects real-world exploitability conditions based on internal research. Second — and more consequentially for defenders — their analysis identified 18 additional downstream packages beyond pac4j-jwt that are affected by the same flaw, bringing the confirmed total to 19 impacted components.
"pac4j ranks among the top 2% most downloaded components on Maven Central, with more than 30,000 vulnerable downloads in the past week alone." — Sonatype Security Research Team, March 11, 2026. (Sonatype)
These additional packages are components that directly depend on pac4j-jwt and inherit the vulnerable JwtAuthenticator behavior. Many Java frameworks and applications pull in pac4j as a transitive dependency, meaning pac4j-jwt may be present in a production environment without the development team ever having added it directly to their dependency manifest. Sonatype's discovery substantially raises the total number of deployments at risk and underscores why vulnerability management approaches that wait for upstream advisory publication before scanning are structurally insufficient for supply chain risks of this kind.
This is not the first time pac4j authentication logic has failed in this general direction. CVE-2021-44878 affected pac4j v5.1 and earlier, where clients could by default accept OpenID Connect ID tokens using the "none" algorithm — meaning no signature whatsoever. CVE-2026-29000 is a different code path but the same conceptual failure: the library can be made to accept identity claims without verifying who produced them, under conditions an attacker can deliberately engineer.
Real-World Impact and Blast Radius
Authentication bypasses are sometimes treated as lower-severity than remote code execution. In practice, the two are often equivalent in operational impact, and in architectures built on shared identity infrastructure, authentication bypass can be considerably worse. An attacker who can forge a token claiming to be any user — including an administrator — gains control over what the entire application believes about their identity. That leads directly to privilege escalation, access to protected data, unauthorized administrative actions, and lateral movement into downstream services that trust the same identity assertions.
"An authentication bypass gives control over what the system believes about who you are. In large systems, identity forgery can lead to privilege escalation, administrative actions, data access, lateral service authorization, or hidden persistence through trusted control planes." — UVCyber Threat Advisory, March 2026. (UVCyber)
The risk multiplies when pac4j is used in shared authentication infrastructure. When a single identity provider, API gateway, or common auth library version is reused across multiple internal applications, a single forged token can propagate trust failures across the entire environment. The UVCyber advisory draws the parallel explicitly: this is the same blast-radius characteristic that made Log4Shell so operationally disruptive. A widely embedded component that turns into a remote, pre-authentication compromise primitive has enterprise-wide consequences, regardless of whether it executes code or forges identity.
The vulnerability's ease of exploitation raises that risk further. No special tooling is required, no privileged network position is needed, and the public key required to craft the exploit is often deliberately exposed by the server itself. CISA's enrichment of the CVE record marks exploitation as automatable — a threat actor could scan for and exploit vulnerable endpoints at scale without manual per-target effort.
Detection: What to Look For
Because the exploit produces tokens that the server successfully decrypts and accepts as valid, detection requires log analysis rather than relying on authentication error signals. Successful exploitation generates no authentication failure — from the server's perspective, the login succeeded. Indicators of potential exploitation include:
- JWT tokens in authentication logs where the inner payload, after JWE decryption, carries an
alg: noneheader - Successful logins for privileged or administrative accounts from IP addresses or geographic locations inconsistent with normal access patterns
- JWT tokens that decrypt successfully but contain no valid signature components when inspected out-of-band
- Anomalous administrative actions performed by accounts with no prior history of elevated activity
- Authentication events from service accounts or system identities at unusual times or from unexpected network sources
- Session creation spikes on authentication endpoints with no corresponding legitimate login events in adjacent systems
The SentinelOne vulnerability database entry for CVE-2026-29000 recommends reviewing all user sessions created during the window between initial library exposure and patching, and invalidating any tokens that may have been forged. Because forged tokens are structurally indistinguishable from legitimate tokens at the application layer, a full session rotation following patching is the conservative and appropriate response for any environment that cannot rule out exploitation during the exposure window.
Remediation and Hardening
The fix is direct: upgrade to a patched release on your major version line. The pac4j project published patched versions for all three active branches simultaneously with the public advisory on March 4, 2026.
4.x line: upgrade to 4.5.9 or later • 5.x line: upgrade to 5.7.9 or later • 6.x line: upgrade to 6.3.3 or later. Verify your version in pom.xml, build.gradle, or by running mvn dependency:tree and checking for org.pac4j:pac4j-jwt. Check transitive dependencies as well — Sonatype confirmed 18 additional packages carry this flaw.
If an immediate upgrade is not possible, the following temporary measures reduce exposure while a patch is staged. Configure JwtAuthenticator to explicitly reject tokens where the inner payload carries alg: none. Implement a pre-validation filter that rejects PlainJWT structures before they reach the authenticator. Apply network-level controls to restrict authentication endpoints to trusted sources. If your deployment does not require JWE and only uses signed JWTs, consider temporarily disabling JWE token support in the authenticator configuration until the patch is applied.
# Locate pac4j-jwt in a Maven project
mvn dependency:tree | grep pac4j-jwt
# Locate pac4j-jwt in a Gradle project
./gradlew dependencies | grep pac4j-jwt
# Patched artifact versions to target
org.pac4j:pac4j-jwt:4.5.9 (minimum for the 4.x line)
org.pac4j:pac4j-jwt:5.7.9 (minimum for the 5.x line)
org.pac4j:pac4j-jwt:6.3.3 (minimum for the 6.x line)
Beyond patching this specific CVE, the broader hardening lesson is to enforce an explicit algorithm allowlist in any JWT validation pipeline. Validate issuer and audience claims in every token. Never treat successful decryption as sufficient evidence of trust. Decryption only demonstrates that the server was capable of reading the message. It does not prove who wrote it. That distinction — confidentiality versus authenticity — is the exact gap this vulnerability exploits.
Key Takeaways
- Patch immediately on your version line. Patched releases exist for 4.x, 5.x, and 6.x. There is no reason to remain on a vulnerable version. Run a full dependency tree scan before assuming your environment is unaffected — pac4j-jwt arrives as a transitive dependency in many stacks.
- Encryption and authentication are not the same thing. This vulnerability exists because the code treated successful decryption as sufficient to trust a token's identity claims. Signatures verify origin and integrity. Encryption verifies confidentiality only. Any system that conflates the two is structurally vulnerable to this class of attack.
- The blast radius extends far beyond the direct dependency. Sonatype confirmed 19 total affected packages. Libraries that depend on pac4j-jwt inherit the vulnerability regardless of whether a team calls pac4j-jwt directly. Transitive dependency scanning is a required step, not an optional one.
- A public key being public is not a mitigating factor — it is the attack vector. The counterintuitive aspect of CVE-2026-29000 is that an attacker needs only a key that is, by design, meant to be distributed. Defense requires signature verification as a mandatory, non-bypassable second step after decryption, enforced at the code level.
- Rotate sessions and audit logs for the full exposure window. Because forged tokens produce successful authentication events with no error signals, the period between vulnerability introduction and patching must be treated as a potential compromise window. Invalidate existing sessions and review logs for the behavioral indicators described in the detection section above.
CVE-2026-29000 is a reminder that identity infrastructure deserves the same scrutiny as network perimeters and endpoint controls. Authentication libraries are trust anchors for entire application stacks. When one fails, it fails across every system that relies on it. The vulnerability was found, patched, and disclosed responsibly through a coordinated process between researchers and an attentive maintainer. The open source security community performed as it should. What remains is for the organizations running the software to act on that work.
Sources: NVD — CVE-2026-29000 • CodeAnt AI Security Research • Sonatype Security Research Team • UVCyber Threat Advisory • OpenCVE — CISA ADP Enrichment • SentinelOne Vulnerability Database • pac4j Official Security Advisory