pac4j JWT Authentication Bypass via Unsigned Token in JWE Wrapper — CVE-2026-29000
by c0gnit00 · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-29000
- Category
- web
- Affected product
- pac4j (JWT authentication module), used in Java web applications
- Affected versions
- Deployments using pac4j with alg: none acceptance and JWE wrapping without inner-JWT signature verification
- Disclosed
- 2026-07-05
- Patch status
- unpatched
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | c0gnit00 |
| CVE / Advisory | CVE-2026-29000 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (Critical) — as stated in source README |
| Status | Weaponized |
| Tags | pac4j, jwt, jwe, auth-bypass, alg-none, jwks, privilege-escalation, java |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | pac4j (JWT authentication module), used in Java web applications |
| Versions Affected | Deployments using pac4j with alg: none acceptance and JWE wrapping without inner-JWT signature verification |
| Language / Platform | Python PoC (requests, jwcrypto) against a Java (pac4j) backend |
| Authentication Required | No (crafts its own forged credential) |
| Network Access Required | Yes |
Summary
A vulnerable pac4j JWT configuration accepts unsigned JWTs (alg: "none") and, when JWE encryption is used to wrap tokens, decrypts the outer JWE and trusts the inner JWT’s claims without independently verifying that the inner token is signed. The PoC builds an unsigned JWT with a payload of role: "ROLE_ADMIN", fetches the target server’s public key from a standard JWKS endpoint (/.well-known/jwks.json or /api/auth/jwks), encrypts the unsigned JWT into a JWE container using that public key, and outputs a token that the vulnerable server will decrypt, trust, and treat as an authenticated admin session. This lets an attacker forge arbitrary roles/claims without ever possessing a valid signing key.
Vulnerability Details
Root Cause
pac4j’s JWT validation path allows alg: none tokens and, for JWE-wrapped tokens, verifies only that the JWE decrypts successfully with the server’s key — it does not separately validate the signature (or lack thereof) of the inner JWT payload, so an attacker-supplied unsigned JWT is accepted as authentic once wrapped in valid JWE encryption.
Attack Vector
- Query the target’s JWKS endpoint to retrieve its RSA public encryption key.
- Construct a JWT with header
alg: noneand a payload containing arbitrary claims (e.g.sub: admin,role: ROLE_ADMIN), leaving it unsigned. - Encrypt the unsigned JWT as a JWE using the fetched public key (RSA-OAEP-256 / A128GCM).
- Submit the resulting JWE as a Bearer token to a protected endpoint.
- The server decrypts the JWE, extracts the unsigned inner JWT, and trusts its claims without signature verification, granting admin-level access.
Impact
Complete authentication and authorization bypass — an unauthenticated attacker can forge tokens with arbitrary roles (including admin) and gain full access to protected application functionality.
Environment / Lab Setup
Target: Java web application using pac4j with alg:none-tolerant JWT + JWE configuration, exposing a JWKS endpoint
Attacker: Python 3 with `requests` and `jwcrypto` (see requirements.txt)
Proof of Concept
PoC Script
See
exploit.pyin this folder.
| |
The script fetches the target’s JWKS, builds an unsigned JWT carrying the requested username/role claims, encrypts it into a JWE using the server’s public key, and prints a ready-to-use Authorization: Bearer <JWE_TOKEN> header for authenticating against protected endpoints.
Detection & Indicators of Compromise
Signs of compromise:
- Log entries showing accepted tokens with
alg: noneor missing signature verification warnings. - Unexplained admin-role sessions correlated with recent JWKS endpoint reconnaissance from the same source IP.
- Configuration audit revealing
setAlgorithmsAllowedForSigning(null)or disabled inner-JWT validation in pac4j setup.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Configure pac4j to reject alg: none and enforce inner-JWT signature verification even when JWE-wrapped; whitelist allowed algorithms (e.g. RS256). No vendor patch confirmed as of 2026-07-05 — monitor for advisory. |
| Interim mitigation | Restrict JWKS endpoint exposure to internal networks, disable JWE wrapping if not required, and add independent signature/claims validation layers in front of pac4j. |
References
Notes
Mirrored from https://github.com/c0gnit00/CVE-2026-29000 on 2026-07-05.
| |