CVE-2026-48525
Description
PyJWT is a JSON Web Token implementation in Python. From 2.8.0 to 2.12.1, when verifying detached JWS tokens using the unencoded-payload option ("b64": false, RFC 7797), PyJWT performs Base64URL decoding of the compact-serialization payload segment before enforcing the detached-payload rules. For b64=false, PyJWT later discards that decoded payload and replaces it with the caller-provided detached_payload. In practice, this turns the middle segment into an attacker-controlled “work amplifier”: a remote client can supply an arbitrarily large Base64URL payload segment that forces CPU work + memory allocations even if the signature is invalid. This creates an unauthenticated DoS vector against any endpoint that verifies detached JWS using PyJWT. This vulnerability is fixed in 2.13.0.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
PyJWT 2.8.0–2.12.1 has an unauthenticated DoS via unbounded Base64URL decoding of unused payload in b64=false detached JWS verification.
Vulnerability
PyJWT versions 2.8.0 to 2.12.1 contain a denial-of-service vulnerability in the verification of detached JWS tokens using the unencoded-payload option ("b64": false, RFC 7797). When processing such tokens, the library performs Base64URL decoding of the compact-serialization payload segment before enforcing detached-payload rules, even though for b64=false that decoded payload is subsequently discarded and replaced with the caller-provided detached_payload. This allows an attacker to supply an arbitrarily large Base64URL payload segment, causing unnecessary CPU and memory consumption, even if the signature is invalid. The vulnerability exists in the _load() method and decode_complete() in jwt/api_jws.py [1].
Exploitation
An unauthenticated remote attacker can send a crafted JWT token with a large Base64URL-encoded payload segment in the compact serialization, targeting any endpoint that verifies detached JWS tokens using PyJWT. No prior authentication or specific privileges are required. The token's signature can be invalid; the library still incurs the decoding cost before rejecting the token. The attack is amplified by the ratio of decoding expansion. Practical amplification depends on upstream request body-size limits; deployments with typical caps (≤2 MB) bound the impact, while those accepting larger inputs are more exposed [1].
Impact
Successful exploitation results in a denial-of-service condition: the target application's CPU and memory resources are consumed by processing the attacker's malicious token, potentially leading to service disruption. The vulnerability is unauthenticated and can be triggered remotely. No other CIA impacts are documented [1].
Mitigation
The vulnerability is fixed in PyJWT version 2.13.0. Users should upgrade to 2.13.0 or later. For systems that cannot upgrade immediately, deploying upstream request body-size limits (e.g., at a proxy, web server, or framework) can mitigate the impact by capping the maximum token size, reducing the amplification factor [1].
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"Unconditional Base64URL decoding of the compact-serialization payload segment in _load() before checking whether b64=false detached-payload rules apply, allowing an attacker to force expensive decoding of an arbitrarily large payload segment that is later discarded."
Attack vector
An unauthenticated remote attacker crafts a JWS compact token with header containing "b64": false and crit: ["b64"], then inflates the middle (payload) segment to millions of Base64URL characters. When a server endpoint calls PyJWS.decode() or decode_complete() with a detached_payload, PyJWT first decodes the inflated segment in _load() — consuming CPU time and allocating large byte buffers — before it checks the b64 flag, discards the decoded payload, and replaces it with the caller-provided detached_payload. The signature is verified only after this expensive decode, so even invalid-signature tokens trigger the full resource consumption [ref_id=1].
Affected code
The vulnerable logic is in jwt/api_jws.py, specifically in PyJWS.decode(), PyJWS.decode_complete(), and the _load() helper. In decode_complete(), _load(jwt) is called first — which unconditionally performs base64url_decode(payload_segment) — and only afterward does the code check header.get("b64") and replace the payload with detached_payload [ref_id=1].
What the fix does
The advisory recommends two safe approaches: either reject a non-empty payload segment when b64=false (raising DecodeError before decoding), or skip Base64URL decoding of the payload segment entirely when b64=false and use only the detached_payload for signing input [ref_id=1]. Both options prevent the unbounded decode of an attacker-controlled segment that is never used for verification. The fix in 2.13.0 restructures the decode order so that the b64 header is inspected before the payload segment is Base64URL-decoded, eliminating the resource amplification vector [ref_id=1].
Preconditions
- configThe server endpoint must call PyJWS.decode() or decode_complete() with a detached_payload argument.
- configThe server must accept tokens with 'b64': false in the JWS header.
- authNo authentication or signing key is required — the attacker can send tokens with invalid signatures.
- networkThe attacker must be able to send HTTP requests to the verification endpoint (network reachability).
- inputThe attacker controls the compact-serialization token string, specifically the middle (payload) segment.
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1News mentions
0No linked articles in our index yet.