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·40 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

•about 15 hours ago•CVE-2026-128087
3.7

CVE-2026-128087: Premature Key Exchange Callback Invocation Prior to Host Key Verification in russh

CVE-2026-128087 (GHSA-9264-jvgf-6w2f) is an incorrect behavior order (CWE-696) and improper authorization (CWE-863) vulnerability in the russh Rust SSH library, affecting versions 0.55.0 through 0.65.0. During the initial SSH key exchange (KEX) handshake, the client state machine invokes the client::Handler::kex_done() callback—providing the negotiated raw shared secret bytes—prior to validating the remote server's host key or certificate via check_server_key(). Consequently, an untrusted or rogue SSH server can complete cryptographic key agreement and force a connecting client to execute side-effecting application logic inside kex_done() before the server's identity is checked and rejected.

Amit Schendel
Amit Schendel
4 views•10 min read
•about 16 hours ago•CVE-2026-128082
7.5

CVE-2026-128082: Uncontrolled Recursion and Denial of Service in AutoMapper via Constructor Parameter Mapping

CVE-2026-128082 (GHSA-6vhm-j9h7-f9gh) is an uncontrolled recursion vulnerability (CWE-674) in AutoMapper, a convention-based object-object mapper for .NET. When mapping nested or self-referential types into destination models that rely on parameterized constructors, C# positional records, or recursive ConstructUsing expressions, AutoMapper evaluates child constructor arguments prior to incrementing the parent's recursion depth counter. This ordering flaw bypasses both explicit MaxDepth limits and the default depth limit of 64. An unauthenticated remote attacker can supply deeply nested input payloads to affected endpoints, exhausting the thread call stack and triggering an uncatchable System.StackOverflowException that terminates the hosting .NET process.

Amit Schendel
Amit Schendel
7 views•11 min read
•about 17 hours ago•CVE-2026-128080
5.8

CVE-2026-128080: Sensitive Query Parameter Disclosure on Incoming Server Spans in OpenTelemetry JavaScript (@opentelemetry/instrumentation-http)

An information exposure vulnerability in the @opentelemetry/instrumentation-http package for OpenTelemetry JavaScript versions 0.204.0 prior to 0.222.0 causes incoming HTTP server spans to record raw, unredacted query string parameters under the url.query attribute. While outgoing client spans applied built-in and user-configured query parameter redaction, incoming server spans bypassed this sanitization completely, resulting in the transmission of sensitive credentials such as pre-signed cloud URLs and API tokens to external observability backends.

Alon Barad
Alon Barad
6 views•10 min read
•about 18 hours ago•CVE-2026-128089
7.5

CVE-2026-128089: Uncontrolled Resource Consumption in dnspython WKS Record Parser

CVE-2026-128089 is an uncontrolled resource consumption vulnerability in the dnspython toolkit for Python, affecting all versions prior to 2.9.2. When parsing Well-Known Service (WKS) records from text via dns.rdtypes.IN.WKS.WKS.from_text(), the parser fails to validate that numeric service port identifiers fall within the RFC 1035 valid range of 0 through 65535. An attacker capable of supplying untrusted zone files or RDATA text strings containing an arbitrarily large service port integer can force the parser to allocate an unbounded bitmap array using an inefficient linear append loop, resulting in severe CPU exhaustion, application hangs, or Out-Of-Memory (OOM) process termination.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 19 hours ago•CVE-2026-126347
3.1

CVE-2026-126347: Open Redirect via Triple-Slash Redirect Paths in Tornado RedirectHandler

CVE-2026-126347 (GHSA-5cjw-f85j-cv6r) is an open redirect vulnerability (CWE-601) in Tornado, an asynchronous Python networking library and web framework. The flaw resides in tornado.web.RedirectHandler when dynamic URL redirection templates incorporate unvalidated user input. Due to a parser differential between RFC 3986 (used by Python's urllib.parse.urlsplit) and the WHATWG URL Standard (used by modern web browsers), inputs containing three or more leading slashes bypass Tornado 6.6.0's validation logic, allowing unauthenticated attackers to redirect users to arbitrary external domains.

Alon Barad
Alon Barad
7 views•11 min read
•about 20 hours ago•CVE-2026-128123
5.9

CVE-2026-128123: Uncaught Exception and Denial of Service in SvelteKit @sveltejs/adapter-node

A Denial of Service (DoS) vulnerability exists in @sveltejs/adapter-node versions 5.5.7 and 6.0.0-next.0 through 6.0.0. When a SvelteKit server route returns a direct response from a fetch() call with a Content-Type of text/event-stream, the Node.js adapter attempts to mutate the response headers to disable proxy buffering. Because headers returned directly by the WHATWG Fetch API carry an immutable guard, this mutation throws an unhandled TypeError, terminating the underlying Node.js process and denying service to all active and subsequent clients.

Alon Barad
Alon Barad
5 views•9 min read