CVE-2026-102265 Overview
CVE-2026-102265 is a denial-of-service vulnerability in PyJWT, the Python implementation of the JSON Web Token (JWT) standards. The flaw resides in PyJWS._load within jwt/api_jws.py. The parser catches ValueError but does not catch RecursionError raised by json.loads when processing a deeply nested token header. As a result, the unhandled exception escapes the documented PyJWT error hierarchy and propagates to the caller. An unauthenticated attacker can send a malformed token to trigger a request-level failure and an HTTP 500 response. The issue affects PyJWT from version 2.13.0 up to but not including version 2.14.0, and is classified under [CWE-674] Uncontrolled Recursion.
Critical Impact
Unauthenticated attackers can crash JWT-processing endpoints by submitting a token whose header contains deeply nested JSON, causing request-level failures on any service using vulnerable PyJWT versions.
Affected Products
- PyJWT 2.13.0
- PyJWT versions prior to 2.14.0
- Python applications and web services that validate JWTs using vulnerable PyJWT releases
Discovery Timeline
- 2026-09-28 - CVE-2026-102265 published to the National Vulnerability Database (NVD)
- 2026-09-30 - Last updated in NVD database
Technical Details for CVE-2026-102265
Vulnerability Analysis
The vulnerability is triggered inside the _load method of the PyJWS class in jwt/api_jws.py. When PyJWT decodes a token, it base64-decodes the header segment and passes the raw bytes to json.loads. Python's JSON parser recursively descends into nested structures. When nesting exceeds the interpreter recursion limit, json.loads raises a RecursionError.
The original code wrapped the call in a try/except ValueError block. RecursionError inherits from RuntimeError, not ValueError, so the exception was never caught. The exception escaped the PyJWT PyJWTError hierarchy and bubbled up to the application layer, terminating request handling with an HTTP 500 error.
Root Cause
The root cause is uncontrolled recursion combined with an overly narrow exception handler. The parser trusted json.loads to only raise ValueError subclasses on malformed input. Because CPython enforces a stack depth ceiling rather than JSON-specific nesting limits, deeply nested JSON produces RecursionError, which the handler did not consider.
Attack Vector
Exploitation requires no authentication and no user interaction. An attacker sends an HTTP request containing a JWT whose header segment decodes to deeply nested JSON such as {"a":{"a":{"a":{...}}}}. Any endpoint that calls jwt.decode, jwt.get_unverified_header, or the lower-level PyJWS API on attacker-supplied input is affected.
Patch Code (from the official fix)
try:
header: dict[str, Any] = json.loads(header_data)
except (ValueError, RecursionError) as e:
raise DecodeError(f"Invalid header string: {e}") from e
if not isinstance(header, dict):
Source: PyJWT commit 06573692. The patch extends the except clause to also catch RecursionError and re-raises it as DecodeError, keeping the failure inside the documented PyJWT error hierarchy.
Detection Methods for CVE-2026-102265
Indicators of Compromise
- HTTP 500 responses returned by endpoints that parse Authorization: Bearer tokens or otherwise invoke PyJWT decoding routines.
- Application logs containing unhandled RecursionError tracebacks originating from json/decoder.py and jwt/api_jws.py.
- Inbound requests carrying JWTs whose base64-decoded header segments exceed typical size or contain long runs of { or [ characters.
Detection Strategies
- Inspect Python application logs and APM traces for stack traces referencing RecursionError and the _load function in jwt/api_jws.py.
- Correlate spikes in HTTP 500 errors on authentication or token-validation endpoints with unusually large Authorization header values.
- Run a software composition analysis (SCA) scan across Python environments to flag installed PyJWT distributions at version 2.13.0.
Monitoring Recommendations
- Alert on repeated RecursionError exceptions surfacing from JWT parsing paths in centralized logging.
- Monitor request rates and 5xx error rates on authentication endpoints for anomalous patterns from single source IPs.
- Track JWT header sizes at the reverse proxy or API gateway and alert when values exceed a sensible ceiling such as 4 KB.
How to Mitigate CVE-2026-102265
Immediate Actions Required
- Upgrade PyJWT to version 2.14.0 or later in all Python environments, containers, and Lambda functions.
- Audit dependency manifests (requirements.txt, pyproject.toml, Pipfile.lock, poetry.lock) for pinned references to PyJWT 2.13.0.
- Rebuild and redeploy container images that bundle vulnerable PyJWT wheels.
Patch Information
The vulnerability is fixed in PyJWT 2.14.0. See the GitHub Release 2.14.0, the GitHub Security Advisory GHSA-8wjv-2p76-3863, and the upstream commit. The fix widens the except clause in PyJWS._load to catch RecursionError and re-raise it as a standard DecodeError.
Workarounds
- Wrap calls to jwt.decode and jwt.get_unverified_header in application code with an additional except RecursionError handler until the upgrade is deployed.
- Enforce a maximum Authorization header size at the reverse proxy, web application firewall, or API gateway to reject oversized tokens before they reach PyJWT.
- Reject requests whose JWT header segments contain excessive nesting depth using a lightweight pre-parser.
# Upgrade PyJWT to the patched release
pip install --upgrade "PyJWT>=2.14.0"
# Verify the installed version
python -c "import jwt; print(jwt.__version__)"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.