On March 3, 2026, the pac4j project published fixes for a maximum-severity vulnerability in its pac4j-jwt module. The flaw, tracked as CVE-2026-29000, is an authentication bypass inside JwtAuthenticator — the component responsible for validating JSON Web Tokens in Java applications built on the pac4j security framework. The vulnerability was assigned a CVSS 3.1 base score of 10.0 and classified under CWE-347: Improper Verification of Cryptographic Signature.
The attack surface is broad. pac4j is embedded across a wide range of Java web applications, API gateways, single sign-on integrations, and microservice architectures. Any deployment running affected versions of pac4j-jwt that accepts encrypted JSON Web Tokens (JWE) and is configured with both an EncryptionConfiguration and a SignatureConfiguration is vulnerable. An attacker who can obtain the server's RSA public key — something many JWT deployments publish deliberately, for example through a JWKS endpoint — can forge a token that the server will accept as fully authenticated.
Patches were released within two business days of private disclosure, and fixed versions are available across all three supported major release lines. If your organization uses pac4j-jwt and has not yet upgraded, this briefing covers everything you need to understand the risk, verify exposure, and remediate.
What Is pac4j-jwt and Who Uses It
pac4j is a Java security framework designed to handle authentication and authorization across a wide variety of protocols and token formats. It is used in enterprise Java applications, Spring-based backends, Play Framework applications, and API management layers. The pac4j-jwt module specifically handles JSON Web Token generation, validation, and profile extraction. Under the hood it relies on the Nimbus JOSE+JWT library — one of the most widely used JOSE implementations in the Java ecosystem — to perform the actual cryptographic operations.
JWT-based authentication in pac4j follows a two-layer security model. The first layer is confidentiality: the token is encrypted as a JSON Web Encryption (JWE) object using the server's RSA public key, so only the server can decrypt its contents. The second layer is authenticity: the inner payload is a signed JSON Web Signature (JWS) object, proving the token was created by a trusted party who holds the corresponding private key. Both layers are supposed to be enforced on every inbound token before any user profile is constructed from the claims inside.
The vulnerability breaks the second layer entirely under a specific but common configuration, collapsing a system designed to verify two things into a system that verifies only one — and then treats success at the first verification as sufficient proof of identity.
The Root Cause: A Null Check That Skips Everything
The flaw was discovered by the CodeAnt AI Security Research Team during automated auditing of open-source packages with prior CVE history. Their tooling flagged an anomaly in the JwtAuthenticator source: a null check on a signedJWT object that sat immediately before the block responsible for signature verification.
According to the CodeAnt AI Security Research Team, their automated reviewer flagged a null check on signedJWT positioned immediately before the signature verification block — a condition that could allow verification to be silently skipped. After a security engineer traced the execution path manually, the flag was confirmed as a true positive: a complete authentication bypass. (CodeAnt AI Security Research, March 2026)
Here is the precise sequence of events when a vulnerable server processes an inbound encrypted token:
- The server receives a JWE (an encrypted token). It decrypts it successfully using the RSA private key. Decryption succeeds because the attacker encrypted their payload with the publicly known RSA public key — which they are permitted to do by design.
- The decrypted payload is an unsigned PlainJWT — a token with
alg: none, meaning no signature is present or expected. JwtAuthenticatorattempts to parse the decrypted content as aSignedJWTby callingtoSignedJWT()on the Nimbus object. Because the inner token is a PlainJWT, Nimbus correctly returns null.- The logic checks whether
signedJWTis null. It is. The entire signature verification block is skipped. - Execution continues normally. The code reads the claims from the unverified PlainJWT — claims the attacker controls entirely — and builds an authenticated user profile from them.
- The attacker is now authenticated as whoever they specified in the
subclaim, with whatever roles they wrote into the token.
The server successfully decrypted attacker-controlled data and treated that success as sufficient proof of identity. Decryption only proves the server could read the message — it says nothing about who created it. The attacker is permitted to encrypt with the public key by design. The missing step is signature verification, and in the vulnerable flow that step disappears entirely. CVE-2026-29000 is classified CWE-347: Improper Verification of Cryptographic Signature. CVSS 3.1 base score: 10.0.
This is not a flaw in RSA cryptography. It is not a flaw in the Nimbus library. It is an application logic error — the gap between "I decrypted this data" and "I verified who sent this data" was never closed. The cryptography did exactly what it was supposed to do. The application code failed to enforce that a decrypted token is not automatically an authenticated token.
Affected Versions and Patch Availability
The vulnerability affects all three currently supported major release lines of org.pac4j:pac4j-jwt. The National Vulnerability Database (NVD), GitHub Advisory Database (GHSA-pm7g-w2cf-q238), and the pac4j project's own security advisory all confirm the same affected ranges and fixed versions.
- 4.x line: all versions before 4.5.9 are vulnerable. Upgrade to 4.5.9 or newer.
- 5.x line: all versions from 5.0.0-RC1 before 5.7.9 are vulnerable. Upgrade to 5.7.9 or newer.
- 6.x line: all versions from 6.0.4.1 before 6.3.3 are vulnerable. Upgrade to 6.3.3 or newer.
Impacted deployments are specifically those configured with both an RSAEncryptionConfiguration and a SignatureConfiguration in JwtAuthenticator. If your application only validates signed JWTs (JWS) and never accepts encrypted tokens (JWE), your direct risk from this specific flaw is lower — but you should still audit your configuration and upgrade to rule out edge cases in your token processing path.
To check your current version in a Maven project, run:
$ mvn dependency:tree | grep pac4j-jwt
In a Gradle project:
$ ./gradlew dependencies | grep pac4j-jwt
Upgrading in Maven requires updating the version in your pom.xml. For the 6.x line, the correct dependency block after patching should read version 6.3.3 or higher. The same version-bump pattern applies to the 4.x and 5.x lines against their respective fixed releases.
An independent security researcher, Matthew Close, reproduced the bypass on March 8, 2026 and contributed an alternative proof-of-concept variant demonstrating that the vulnerable path can also be reached by sending raw JSON claims directly as the JWE payload rather than a nested PlainJWT. This means there are at least two distinct attack payloads that trigger the same underlying logic failure, further confirming that the vulnerability is not an edge case or difficult-to-reach condition.
Which Frameworks and Products Pull pac4j-jwt Transitively?
The takeaway here is not limited to developers who consciously chose pac4j-jwt. A significant portion of vulnerable deployments will belong to teams who depend on it without knowing it, because a higher-level framework declared it as a dependency on their behalf.
The most common transitive vectors include: Apache Shiro with the shiro-pac4j integration, which brings in pac4j-jwt when JWE-based token support is configured; Play Framework applications using the pac4j Play module, which is widely used in Scala-based backends; Buji-pac4j, the Shiro binding for pac4j used in many legacy enterprise Java stacks; and various API gateway configurations that use pac4j as a pluggable authentication provider. Additionally, internal shared authentication libraries — custom modules written once at an organization and reused across many services — frequently embed pac4j-jwt to avoid duplicating JWT handling code, creating a many-to-one exposure where a single internal library update can quietly spread a vulnerable version across dozens of services.
If your application uses any pac4j integration module — not just pac4j-jwt directly — run the full dependency tree before concluding you are unaffected. The output of mvn dependency:tree | grep pac4j will surface any pac4j module in the graph. If pac4j-jwt appears at any depth and falls within the affected version ranges, you are exposed regardless of whether you declared it.
Real-World Impact and Blast Radius
Authentication bypass vulnerabilities are frequently miscategorized as less severe than remote code execution because they do not directly execute arbitrary commands. That framing misunderstands how enterprise breaches actually propagate. When an attacker can forge identity at the authentication layer, they gain control over what every downstream system believes about who they are.
Arctic Wolf's advisory characterizes this as full account compromise within any system where pac4j-derived JWT claims establish authentication and authorization context. The most severe outcomes — administrator impersonation, privilege escalation, and downstream service access — can become enterprise-wide if a shared identity provider or common library version is reused across multiple internal applications. (Arctic Wolf, CVE-2026-29000 Advisory, March 2026)
Consider a few common pac4j deployment patterns and what exploitation looks like in each:
Internet-Facing Web Application
An attacker who knows the application uses pac4j-jwt (discoverable through error messages, HTTP headers, or dependency scanning of public repositories) can query the JWKS endpoint or extract the RSA public key from any valid token. They craft a JWE-wrapped PlainJWT asserting they are an administrator account, submit it as a bearer token, and gain full administrative access to the application. No credential theft. No phishing. No brute force. The attack requires only the public key and a working knowledge of the JWT format.
API Gateway or SSO Integration Point
Many organizations use pac4j at an API gateway layer that issues session tokens consumed by multiple backend services. A forged identity assertion at the gateway propagates to every downstream service that trusts the gateway's claims. A single successful exploit can cascade into compromise of multiple systems in a single request. This is the pattern Arctic Wolf specifically calls out as elevating the blast radius from a single application to an enterprise-wide trust failure.
Microservice Architectures
In zero-trust or service-mesh architectures where JWTs are used for service-to-service authentication, an attacker who can forge tokens with arbitrary claims can impersonate internal services. Depending on what claims are used for authorization gating, this may allow access to data stores, internal APIs, and administrative control planes that are not exposed to the internet but do trust assertions carried in JWT format.
The Attacker's Timeline: From Advisory to Working Exploit
The gap between disclosure and weaponization is a practical operational number, not an abstract risk metric. The pac4j advisory was published March 3, 2026. An independent proof-of-concept from a second researcher, Matthew Close, appeared March 8 — five days later. That is the outside bound of the window that organizations had before the attack surface was demonstrably accessible to anyone willing to read a security research post.
For organizations with structured patch management processes — change control boards, required testing windows, and tiered deployment schedules — five days is not a realistic patch cycle. It is a period during which an unpatched deployment is sitting behind nothing except attacker awareness. And attacker awareness scales quickly once a PoC is public: automated scanners, threat actors monitoring NVD feeds, and opportunistic scanning infrastructure all operate on timelines measured in hours, not weeks.
The realistic attacker profile for this vulnerability requires: knowledge that a target uses pac4j-jwt (fingerprinted from error messages, HTTP headers, JWKS endpoint exposure, or public repository scanning), the target's RSA public key (obtainable through JWKS, from a valid token, or from public configuration), and the ability to craft and submit a bearer token. No credentials. No insider access. No vulnerability chaining. This sits firmly in the category of "script kiddie accessible after reading one blog post" — which is exactly why patching and interim controls cannot wait on bureaucratic timelines.
As of March 2026, Arctic Wolf and other tracking sources have not confirmed active exploitation in the wild. However, public proof-of-concept code has been available since March 8, 2026, and the attack requires no credentials and no chaining. The absence of confirmed exploitation is not an absence of exploitation. Unpatched systems should be treated as exposed from the date PoC became public.
This vulnerability carries a structural similarity to Log4Shell (Log4j, CVE-2021-44228) in one important way: pac4j-jwt is a widely embedded dependency, often pulled in transitively by frameworks and application stacks rather than declared explicitly. Organizations may be running vulnerable versions without knowing they depend on pac4j at all. Run a full dependency tree analysis — not just a top-level dependency check — before concluding you are not exposed.
Detection: How to Know If You Have Been Targeted
Because exploitation requires only network access and the RSA public key, there are no precursor indicators like credential stuffing or brute-force traffic that typically signal an impending account takeover. The attack arrives as a single, well-formed HTTP request carrying a token that looks structurally valid to any logging or WAF layer that does not inspect JWT signature state.
Security teams should look for the following indicators in authentication logs and token processing infrastructure:
- Authentication events where the JWT contains a
alg: noneinner token — most legitimate signed tokens will carry a specific RSA or EC algorithm identifier, notnone. - Successful authentications from accounts that have no corresponding session history, login event, or recent activity prior to the anomalous authentication.
- Administrator or privileged-role authentications originating from IP addresses or user agents not associated with known administrators.
- Token processing log entries where decryption succeeded but no signature verification record was written — in patched deployments, a missing verification log entry for a JWE token should be treated as suspicious.
- JWE tokens whose inner payload is a raw JSON object rather than a nested compact JWT string (the Matthew Close variant).
If your organization does not currently log JWT algorithm headers and inner token types as part of authentication event records, add that instrumentation now. The most dangerous aspect of this attack is that it is silent at the network layer — it looks like a successful, authorized authentication to any system that does not inspect what the token actually contained.
Remediation and Hardening Steps
If You Cannot Patch Immediately: Interim Mitigations
Patching is non-negotiable, but it is not always instantaneous. Organizations with change control requirements, compliance-gated deployment windows, or applications on unmaintained internal forks need something to stand behind while the patch moves through process. The following interim measures reduce — but do not eliminate — your exposure.
Block or strip JWE tokens at the perimeter where possible. If your application currently accepts both JWS tokens and JWE tokens, and you can identify which endpoints require encrypted token support, consider temporarily restricting or rejecting JWE-formatted bearer tokens at a WAF or reverse proxy layer for the period between detection and patching. This is not feasible for every deployment, but in cases where JWE support is not actively needed at specific endpoints, temporarily requiring plain signed JWTs removes the attack vector without touching application code.
Add a server-side pre-validation filter. A thin servlet filter or middleware component that inspects the alg claim of the outer token and rejects any bearer token where the inner JWE payload, once decoded but before being handed to pac4j, parses as a PlainJWT (three-segment structure, "alg":"none") provides an application-layer circuit breaker. This is defensive coding, not a substitute for the patch, and it carries its own implementation risk if done carelessly — but it is a meaningful control for environments where the patch cannot deploy in days.
Increase authentication log monitoring immediately. Even before patching, enable alerting on the indicators described in the Detection section: privileged authentications from unknown IPs, administrator sessions with no prior activity history, and authentication events lacking a corresponding signature verification log entry. You may not be able to prevent exploitation immediately, but you can shorten detection time and limit dwell.
None of these measures close the vulnerability. They buy time while the patch moves through your process. Document them as temporary controls with an expiration date, because interim mitigations that become permanent are a separate risk category.
The primary remediation is upgrading to a patched release. That action is non-negotiable. Everything below is defense-in-depth that should accompany the upgrade, not replace it.
- Upgrade pac4j-jwt immediately. Apply the appropriate fixed version for your major line: 4.5.9+, 5.7.9+, or 6.3.3+. Prioritize internet-facing services and any component that participates in SSO or cross-service authentication.
- Inventory transitively included versions. Run a full dependency tree scan. Many applications include pac4j-jwt through a higher-level pac4j integration module rather than declaring it directly. Tools like
mvn dependency:tree,./gradlew dependencies, or OWASP Dependency-Check can surface transitive inclusions. If your organization maintains a Software Bill of Materials (SBOM), query it immediately for any component declaringorg.pac4j:pac4j-jwtas a dependency — this is exactly the scenario SBOMs are designed to accelerate. - Enforce explicit JWT algorithm allowlists. Configure
JwtAuthenticatorto explicitly rejectalg: nonetokens at the outer and inner payload level. After patching this vulnerability, the library enforces this — but review custom middleware and filter chains for any local token glue code that may repeat the same trust mistake. - Validate issuer and audience claims. Ensure that every JWT processing path enforces
issandaudclaims. This adds a layer of trust context that makes forged tokens with valid-looking claims harder to pass into restricted contexts. - Review downstream service trust relationships. Map which services accept identity assertions from pac4j-authenticated components. If those downstream services perform no independent claim verification and trust pac4j's output implicitly, a successful exploit before patching may already have created persisted access that the patch alone will not remove.
- Check authentication logs for exploitation indicators covering the period from initial deployment of affected versions through the date of patching. If you find anomalous administrator-level authentications in that window, treat the environment as potentially compromised and investigate accordingly.
- Monitor for post-patch recurrence. After upgrading, run test requests carrying JWE-wrapped PlainJWT payloads against your authentication endpoints. A correctly patched deployment should reject these with an authentication failure. If they succeed, something in your token processing chain is still vulnerable.
Deeper Hardening: Beyond the Patch
The seven steps above address the immediate vulnerability. The following measures address the structural conditions that allowed it to exist and that will matter long after this specific CVE is resolved.
Integrate SBOM-driven alerting into your CI/CD pipeline. CVE-2026-29000 became exploitable in organizations that did not know they depended on pac4j-jwt. The underlying problem is not a slow patch cycle — it is an absence of dependency visibility. If your build process generates and publishes a CycloneDX or SPDX SBOM, configure your vulnerability scanner to alert on any new CVE that touches a component in that SBOM the moment it is published to NVD. The gap between disclosure (March 3, 2026) and public PoC availability was measured in days. Teams with automated SBOM-based alerting could close that gap; teams without it could not.
Write and run JWT algorithm confusion test suites. After patching, build a persistent regression test that submits crafted tokens covering every documented JWT attack class: alg: none inner tokens, JWE-wrapped PlainJWTs, algorithm substitution (RS256 → HS256 with the public key as the HMAC secret), missing signature segments, and raw JSON payloads as JWE inner content (the Matthew Close variant). These tests should run on every build, not as a one-time post-patch check. If a future library update or configuration change reintroduces a vulnerable path, this suite will catch it before production.
Implement runtime token inspection at the authentication boundary. WAF rules can be configured to inspect JWT algorithm headers and inner token structure. A rule that flags or blocks any inbound bearer token where the JWE inner payload parses as a PlainJWT (identifiable by the three-segment structure with a header containing "alg":"none") provides a network-layer defense that operates independently of whether any application library is patched. This is not a substitute for patching — a sophisticated attacker can encode around simple pattern matching — but it raises the cost of exploitation and provides a logging signal even against attacks you did not anticipate.
Consider token binding for high-value authentication contexts. Token binding (RFC 8471) ties a JWT to a specific TLS connection by incorporating a cryptographic commitment to the connection in the token itself. A stolen or forged token cannot be replayed from a different connection because the binding proof fails. This does not directly prevent CVE-2026-29000-style forgery — an attacker making a direct request does not need to replay a token — but it significantly reduces the value of forged tokens that are intended to be passed laterally between services. In microservice architectures where service-to-service JWTs can move through multiple hops, token binding raises the bar for the propagation phase of an attack.
Apply zero-trust re-verification patterns at privilege escalation boundaries. Even in patched deployments, consider requiring step-up authentication for administrative operations rather than relying entirely on the initial JWT assertion. A user who authenticates with a valid JWT to access standard functionality should face a second verification step — ideally using a different factor and a different authentication path — before accessing administrative endpoints. This does not prevent authentication bypass at the initial boundary, but it prevents an authentication bypass at the standard tier from immediately cascading to full administrative control.
Audit the pac4j-core deserialization surface if you have not already. If your application uses pac4j-core and stores any externally controlled values (usernames, emails, or other user-supplied strings) as attributes on UserProfile objects, verify you are on version 4.0.0 or later. CVE-2023-25581 is a distinct but serious vulnerability in the broader pac4j ecosystem, and organizations focused narrowly on the JWT bypass may have missed it if they upgraded only pac4j-jwt without auditing the full pac4j dependency tree.
The Broader Pattern: Why JWT Libraries Keep Getting This Wrong
CVE-2026-29000 is not the first time pac4j has had a vulnerability rooted in the gap between token parsing and trust verification. CVE-2021-44878 (NVD, GitHub Advisory Database) affected pac4j v5.3.0 and prior — specifically the pac4j-oidc module — where clients could, by default, accept OpenID Connect ID tokens using the none algorithm if the identity provider offered it. The specific code path differs from the 2026 JWT bypass, but the conceptual failure is identical: a token was accepted as authenticated without the system confirming who created it or that a valid signature existed.
A separate and distinct class of pac4j risk appears in CVE-2023-25581 (NVD, GitHub Security Lab). That vulnerability affected pac4j-core prior to version 4.0.0, where externally controlled values stored in attributes of the UserProfile class could be exploited by providing a specially crafted string with the {#sb64} prefix followed by a Base64-encoded serialized Java object, triggering unsafe deserialization that could — in the worst case — lead to Remote Code Execution. This is a completely different attack class from the 2026 JWT bypass, but it reaches the same observation: identity objects in pac4j are not passive data containers. They are active trust artifacts, and every code path that writes attacker-controlled data into them without rigorous verification is a potential attack surface.
Taken together, CVE-2021-44878, CVE-2023-25581, and CVE-2026-29000 describe a consistent architectural risk pattern across the pac4j ecosystem: the trust boundary between unverified input and authenticated identity state is thin, and it has been crossed in multiple distinct ways across multiple release lines and modules. The library is actively maintained and patch response has been fast, but these three entries reinforce that pac4j requires active security posture — not passive dependency trust — from the teams deploying it.
What About EC (Elliptic Curve) Encryption Configurations?
The published research and all vendor advisories frame CVE-2026-29000 in terms of RSA-based JWE configurations, because RSA is the dominant encryption scheme in pac4j deployments and the clearest attack path involves RSA-OAEP encryption. But the underlying logic flaw — the null check that skips signature verification when an inner PlainJWT is encountered — is not specific to RSA. It lives in the authentication flow for encrypted token processing generally.
If your deployment uses EC-based JWE configurations (for example, ECDH-ES key agreement), the same structural failure can be triggered by the same attack pattern: craft a JWE using the server's public key, embed an unsigned PlainJWT as the inner token, and submit it as a bearer token. The decryption step and the token type dispatch that follows are conceptually identical regardless of the outer encryption algorithm. The safe assumption is that any configuration pairing a JweConfiguration with a SignatureConfiguration is vulnerable in the affected version range, not only RSA-specific ones. If you are running EC-based key configurations and have been deferring patching on the assumption that EC configurations are unaffected, patch immediately.
What the Fix Actually Does in Code
Understanding the patch mechanism matters because it helps you verify remediation is complete and gives you a template for auditing similar code paths elsewhere. The core fix enforces that when JwtAuthenticator is configured with both an EncryptionConfiguration and a SignatureConfiguration, the decrypted JWE payload must contain a nested signed JWT. If toSignedJWT() returns null — meaning the inner token is a PlainJWT or any other non-JWS type — the authenticator now raises a hard authentication failure rather than silently advancing to profile creation. Execution does not reach createJwtProfile() without a positive signature verification result. The null check that previously gated the verification block no longer functions as an implicit bypass of the verification requirement.
The fix is structurally simple: a permissive null-check bypass becomes a mandatory enforcement point. This is also why the patch requires no configuration changes on the application side — the correct behavior is now enforced within the library itself rather than delegated to consumer configuration. You do not need to add explicit alg: none rejection logic in your filter chain. The patched library will reject attack tokens before your application code ever sees their claims. That said, any custom JWT processing logic sitting outside pac4j — a hand-written authentication filter, a legacy token bridge, a service-to-service authentication shim — is not covered by this patch and should be audited separately for the same pattern.
Does Publishing a JWKS Endpoint Increase Your Risk?
Yes, contextually — but it is not the root cause and removing it is not the right mitigation. An attacker can obtain the server's RSA public key through a JWKS endpoint, from any valid JWT that embeds the public key in its header, via TLS certificate inspection, or sometimes through publicly accessible repository configuration files. JWKS endpoints are a recommended practice in modern OAuth and OIDC deployments, designed to support key rotation and discovery. The correct takeaway is not to hide public keys. It is to understand that any system using RSA-JWE as a confidentiality mechanism must enforce an independent signature check for authenticity, because the public key — by design — is not a secret. CVE-2026-29000 is the consequence of a system that enforced confidentiality and treated it as equivalent to authenticity. The JWKS endpoint made the attack marginally easier; the missing null-check enforcement made it possible.
Is This a JWT Problem?
No. JWT as a specification is not the problem. RFC 7519, RFC 7516 (JWE), and RFC 7515 (JWS) define clear, distinct security properties for different token types, and the Nimbus JOSE+JWT library that pac4j uses as its cryptographic foundation implements those specifications correctly. toSignedJWT() returning null for a PlainJWT is correct behavior — it accurately reflects that the token is unsigned. The flaw lives entirely in application logic: pac4j treated that null return as a non-event rather than a hard stop. Teams that respond to this vulnerability by questioning whether to use JWTs at all are solving the wrong problem. Teams that audit whether their JWT processing pipelines enforce both security properties — confidentiality and authenticity — independently and explicitly are solving the right one.
This pattern — where a library processes attacker-controlled input, finds it parseable or decryptable, and then treats that processing success as trust — appears repeatedly across the history of JWT security. The JWT specification itself was revised over time to address the alg: none confusion, and libraries like Nimbus have hardened their defaults. But application-layer code sitting above those libraries can still create the same vulnerability by failing to couple token processing tightly to verification results.
"A decrypted token is not automatically an authenticated token." — pac4j project, post-patch security documentation (pac4j.org, March 2026)
The updated pac4j documentation now makes this explicit, distinguishing clearly between how plain, signed, and encrypted JWTs should be handled, and requiring that when signatures are configured, a nested signed JWT must be present inside any JWE. That documentation language is worth propagating to any team that writes custom JWT middleware, implements token processing pipelines, or extends authentication frameworks.
The lesson is not that JWT is broken or that RSA is unsafe. The lesson is that encryption and authentication are distinct properties. A system that enforces only one and calls itself secure has cut its attack surface in half while believing it has eliminated it entirely. CVE-2026-29000 is a precise, reproducible demonstration of what happens when that confusion reaches production.
Key Takeaways
- Patch immediately: All pac4j-jwt deployments running versions prior to 4.5.9, 5.7.9, or 6.3.3 are vulnerable if they accept JWE tokens with both encryption and signature configurations active. The fixed versions are available now and the upgrade path is straightforward.
- Check for transitive inclusion: Many Java applications include pac4j-jwt without declaring it directly. Run a full dependency tree scan before concluding you are not affected. A top-level dependency check is not sufficient. If you maintain an SBOM, query it immediately.
- Audit your authentication logs: Proof-of-concept code has been publicly available since shortly after disclosure. The attack is low-skill and pre-authenticated. Review logs for the indicators described above covering the full window your affected version was deployed.
- Encryption is not authentication: The root cause here is the conflation of two separate security properties. Review any custom token processing code in your stack for the same pattern — code that decrypts successfully and proceeds without enforcing that the result also carries a valid signature.
- Monitor after patching: Test your patched deployment actively with crafted unsigned tokens. Log JWT algorithm headers. Set alerts for authentications carrying
alg: noneinner tokens. Defense-in-depth does not end at upgrading the library. - Think beyond the immediate CVE: CVE-2026-29000, CVE-2021-44878, and CVE-2023-25581 form a pattern. pac4j has a history of trust boundary failures across multiple modules and release lines. Any deployment of the pac4j ecosystem warrants an active security posture — dependency scanning, SBOM integration, and ongoing authentication log review — not a one-time patch and move on.
CVE-2026-29000 is a textbook example of a maximum-severity library vulnerability: widely embedded, pre-authenticated, requiring minimal attacker skill, with public exploit code available and a blast radius that scales with how broadly the library is trusted. The patch is simple. The risk of not patching is not.
- [1] NVD — nvd.nist.gov/vuln/detail/CVE-2026-29000
- [2] GitHub Advisory Database — GHSA-pm7g-w2cf-q238
- [3] CodeAnt AI Security Research — pac4j-jwt Authentication Bypass: Full Disclosure
- [4] Arctic Wolf — CVE-2026-29000 Advisory
- [5] CIS Advisory — Authentication Bypass in pac4j-jwt (JwtAuthenticator)
- [6] GitLab Advisory Database — org.pac4j/pac4j-jwt CVE-2026-29000
- [7] pac4j Project Security Advisory — pac4j.org Security Advisory
- [8] GitHub Advisory Database — GHSA-xhw6-hjc9-679m: CVE-2021-44878 (pac4j-oidc none algorithm bypass)
- [9] GitHub Security Lab — GHSL-2022-085: CVE-2023-25581 (pac4j-core Java deserialization)
- [10] NVD — nvd.nist.gov/vuln/detail/CVE-2023-25581