CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-101918

CVE-2026-101918: Unauthenticated Denial of Service via Recursion Exhaustion in PyJWT

Alon Barad
Alon Barad
Software Engineer

Sep 30, 2026·5 min read·5 visits

Executive Summary (TL;DR)

An unauthenticated remote attacker can crash Python web servers using PyJWT by transmitting a token with thousands of nested JSON brackets, triggering an uncaught RecursionError and resulting in a Denial of Service (DoS).

A Denial of Service (DoS) vulnerability exists in the PyJWT library when parsing unverified token payloads containing deeply nested JSON structures. Because PyJWT fails to catch RecursionError during payload parsing, an unauthenticated remote attacker can crash the application thread or worker by sending a specially crafted token.

Vulnerability Overview

PyJWT is a Python implementation of the JSON Web Token (JWT) standards. The vulnerability resides in the pre-verification payload parsing routines of PyJWT. Specifically, when applications perform dynamic signing key lookups (such as using PyJWKClient.get_signing_key_from_jwt) or decode tokens with signature verification explicitly disabled (verify_signature=False), PyJWT decodes and parses the token's payload prior to validating its cryptographic signature.

This architecture creates an unauthenticated attack surface. An attacker can submit an arbitrary payload that forces parsing operations before cryptographic validation is performed. This issue is classified under CWE-248 (Uncaught Exception) and CWE-400 (Uncontrolled Resource Consumption), allowing an unauthenticated remote attacker to trigger a Denial of Service (DoS) against applications utilizing vulnerable versions of PyJWT.

Root Cause Analysis

The root cause of this vulnerability lies in PyJWT's failure to catch the native RecursionError raised by CPython's standard library JSON parser during payload deserialization. The default parser, json.loads, uses a recursive-descent parsing algorithm to process nested structures. Each layer of nested arrays ([ or ]) or objects ({ or }) increases the depth of the interpreter's call stack.

CPython enforces a hard execution call stack depth limit, typically set to 1,000 frames. When the standard JSON parser encounters structures with nesting that exceeds this threshold, the interpreter halts execution and raises a native RecursionError to prevent process-level stack overflow. PyJWT wrapped the parsing statement json.loads(decoded["payload"]) in a try-except block configured to catch only ValueError. Because RecursionError inherits from RuntimeError rather than ValueError, the exception bubbles up through the application execution context and crashes the thread or process handling the request.

Code Analysis

The vulnerability exists in jwt/api_jwt.py within the helper function _decode_payload. Below is a code block illustrating the vulnerable implementation alongside the subsequent patch implemented in version 2.15.0.

# Vulnerable Code in PyJWT < 2.15.0
def _decode_payload(self, decoded: dict[str, Any]) -> dict[str, Any]:
    try:
        # Highly nested payload structures raise a RecursionError here
        payload: dict[str, Any] = json.loads(decoded["payload"])
    except ValueError as e:
        # Only ValueError (and its subclass JSONDecodeError) is intercepted
        raise DecodeError(f"Invalid payload string: {e}") from e
    if not isinstance(payload, dict):
        raise DecodeError("Invalid payload string: must be a json object")

The fix updates the exception target to handle both ValueError and RecursionError. This converts interpreter-level stack crashes into structured, catchable application-level exceptions.

# Patched Code in PyJWT >= 2.15.0
def _decode_payload(self, decoded: dict[str, Any]) -> dict[str, Any]:
    try:
        payload: dict[str, Any] = json.loads(decoded["payload"])
    except (ValueError, RecursionError) as e:
        # RecursionError is now safely caught and wrapped
        raise DecodeError(f"Invalid payload string: {e}") from e
    if not isinstance(payload, dict):
        raise DecodeError("Invalid payload string: must be a json object")

This adjustment ensures that payload parsing errors do not cause the entire process or execution worker to terminate.

Exploitation Methodology

To exploit this vulnerability, a remote attacker generates a JWT with a payload containing deeply nested JSON arrays or objects. Because payload parsing occurs before signature verification, the token's cryptographic signature block can be left empty or contain dummy bytes. No secret keys or credentials are required.

The typical attack workflow is described below:

By repeatedly transmitting this payload to endpoints that perform dynamic key lookup or unverified decodes, an attacker can consume and crash all available application worker threads, leading to complete service exhaustion.

Impact Assessment

The primary impact of this vulnerability is service degradation or complete Denial of Service. In synchronous web frameworks (such as Django, Flask, or WSGI deployments), crashing a worker thread with an unhandled exception interrupts active client connections and drops active tasks. In asynchronous runtimes (such as FastAPI or Sanic), unhandled errors in async paths can disrupt the entire event loop.

The exploit is highly asymmetric. A payload containing 20,000 open brackets occupies roughly 40 kilobytes of space, yet it is sufficient to exhaust the execution stack on a default CPython environment. This allows an attacker with minimal network resource constraints to impair the availability of identity management and API gateway systems.

Remediation and Mitigation

The primary remediation step is upgrading PyJWT to version 2.15.0 or higher, which catches the stack exhaustion exception and raises a standard DecodeError instead.

In environments where upgrading the library is not immediately possible, security teams should implement pre-verification middleware to restrict payload depth. The following filter validates token string structure prior to parsing:

import base64
 
def validate_jwt_nesting_depth(raw_token: str, max_depth: int = 50) -> bool:
    parts = raw_token.split(".")
    if len(parts) < 2:
        return False
    try:
        # Safely pad and decode base64 payload bytes
        payload_bytes = base64.urlsafe_b64decode(parts[1] + "==")
        depth = 0
        for byte in payload_bytes:
            if byte in (91, 123):  # '[' or '{'
                depth += 1
                if depth > max_depth:
                    return False
            elif byte in (93, 125):  # ']' or '}'
                depth = max(0, depth - 1)
        return True
    except Exception:
        return False

Enforcing rate limiting on public-facing endpoints and establishing restrictive HTTP request timeout parameters will also mitigate exploitation attempts.

Official Patches

jpadillaOfficial patch fixing the RecursionError handling

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
EPSS Probability
0.29%
Top 80% most exploited

Affected Systems

Python web applications and microservices using PyJWT versions >= 2.0.0a1 and < 2.15.0 to decode tokens pre-verification or with disabled signature validation.

Affected Versions Detail

Product
Affected Versions
Fixed Version
pyjwt
jpadilla
>= 2.0.0a1, < 2.15.02.15.0
AttributeDetail
CWE IDCWE-248 / CWE-400
Attack VectorNetwork (AV:N)
CVSS Score5.3 (Medium)
EPSS Score0.00291 (Percentile: 19.51%)
ImpactDenial of Service (DoS)
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion
Impact
CWE-248
Uncaught Exception

The software does not explicitly handle or catch an exception that can be thrown within its execution block, resulting in sudden termination of the program or thread.

Known Exploits & Detection

GitHub AdvisoryExploit methodology and context details regarding unauthenticated payload recursion limits

Vulnerability Timeline

Pre-verification security issue identified in PyJWT payload parsing
2026-09-11
Fix commit 5fde08a6cf906aa7698de2d6391d88b73006b17b merged
2026-09-22
PyJWT 2.15.0 released and GHSA-42vr-xj54-vc7v published
2026-09-28

References & Sources

  • [1]GitHub Security Advisory GHSA-42vr-xj54-vc7v
  • [2]PyJWT 2.15.0 Release Notes
  • [3]NVD Vulnerability Details for CVE-2026-101918

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•18 minutes ago•CVE-2026-97711
2.3

CVE-2026-97711: Cross-Site Scripting (XSS) via Unescaped Script-Closing Tags in serialize-javascript

A security vulnerability in serialize-javascript v7.1.1 allows Cross-Site Scripting (XSS) due to an overly greedy regular expression (SCRIPT_CLOSE_REGEXP) used during function serialization. Two secondary defects involving a spoofed toString() validation bypass and a stateful native code validator are also addressed in the fixed version v7.1.2.

Alon Barad
Alon Barad
0 views•7 min read
•about 2 hours ago•GHSA-VCVR-R3JV-PC5J
9.8

CVE-2026-94545: SVG-Serialization Markup Injection in Vercel Satori and Next.js ImageResponse

An improper output encoding and escaping vulnerability (CWE-116) in Vercel Satori allows unauthenticated remote attackers to perform markup injection in dynamic Open Graph images generated via Next.js's ImageResponse. Unsanitized parameter interpolation into SVG elements breaks XML structural boundaries. This exposes downstream parsing, rasterization, and rendering pipelines to Server-Side Request Forgery (SSRF), Local File Read, and Remote Code Execution (RCE).

Alon Barad
Alon Barad
6 views•7 min read
•about 3 hours ago•CVE-2026-102265
5.3

CVE-2026-102265: Unhandled RecursionError in PyJWT JSON Parser Leading to Denial of Service

An uncontrolled recursion vulnerability exists in PyJWT from version 2.13.0 to 2.14.0. The vulnerability allows remote, unauthenticated attackers to cause a Denial of Service (DoS) via crafted JWT headers that trigger stack exhaustion during JSON decoding.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 4 hours ago•CVE-2026-102266
7.4

CVE-2026-102266: Signature Verification Bypass in PyJWT via Empty JWK

A signature verification bypass vulnerability in PyJWT allows unauthenticated remote attackers to forge JSON Web Tokens when processing JSON Web Key Sets containing an empty symmetric key.

Alon Barad
Alon Barad
5 views•8 min read
•about 5 hours ago•GHSA-V53P-9FQP-M79J
7.5

GHSA-V53P-9FQP-M79J: Regular Expression Denial of Service (ReDoS) in Nodemailer addressparser

A Regular Expression Denial of Service (ReDoS) vulnerability exists in Nodemailer's addressparser fallback engine before version 10.0.6. Under specific malformed inputs with excessive word boundaries, the parser exhibits quadratic backtracking, leading to high CPU utilization and event loop blockage.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 6 hours ago•GHSA-G57G-F23G-4646
6.5

GHSA-G57G-F23G-4646: Parser Differential and SMTP Injection in Nodemailer Address Parser

Nodemailer versions prior to 10.0.9 are vulnerable to a parser differential bug. When processing a quoted local-part followed by an RFC 5322 comment and trailing characters, the internal addressparser module fails to order its normalization routine correctly. This error results in the generation of malformed envelope recipient addresses containing injected whitespace and secondary domains, allowing attackers to bypass routing restrictions and exfiltrate sensitive emails.

Alon Barad
Alon Barad
4 views•7 min read