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-102265

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 30, 2026·5 min read·6 visits

Executive Summary (TL;DR)

PyJWT fails to catch RecursionError during JSON header parsing, allowing remote attackers to crash request-handling threads with malformed JWTs.

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.

Vulnerability Overview

PyJWT is a Python implementation of the JSON Web Token (JWT) standards. The library is widely used in web applications to decode and verify security tokens before executing application logic. This role puts PyJWT on the outer perimeter of the application, exposing its parsing code directly to unauthenticated network input.

During the initial decoding stage of a JSON Web Signature (JWS) or JWT, the library parses the base64url-encoded header segment. This parsing must occur before signature verification, as the header contains critical metadata such as the algorithm used to sign the payload. Consequently, any parsing flaw in this phase can be reached without valid credentials or a verified cryptographic signature.

The vulnerability is classified under CWE-674 (Uncontrolled Recursion). By supplying a crafted JWS containing a deeply nested structure in the header, an attacker can exhaust the CPython call stack. This results in an unhandled interpreter exception that escapes the library's exception wrapper and crashes the active processing thread.

Root Cause Analysis

The vulnerability lies in how the standard Python json.loads decoder operates and how PyJWT handles the errors it raises. The CPython standard library JSON decoder utilizes a recursive-descent parser. When processing nested JSON arrays or dictionaries, the decoder recursively allocates call frames on the interpreter's stack to track state.

If the recursion depth exceeds CPython's execution limit, which is typically governed by the sys.getrecursionlimit() value, the interpreter raises a native RecursionError. In python's class hierarchy, RecursionError inherits from RuntimeError, which in turn inherits from the base Exception class.

In vulnerable version 2.13.0, the PyJWS._load method wrapped the decoding statement in a try-except block that explicitly intercepted only ValueError. Because RecursionError does not inherit from ValueError, it bypassed the exception handler. The exception then bubbled up through the application web server, causing the handling worker to terminate prematurely and return an HTTP 500 error.

Code Analysis & Patch Walkthrough

The vulnerability exists in jwt/api_jws.py inside the internal helper method _load. This method is responsible for splitting the three-part compact token representation, decoding the payload, and reconstructing the Python dictionary representing the header.

Below is the vulnerable implementation of the parsing try-block:

try:
    header: dict[str, Any] = json.loads(header_data)
except ValueError as e:
    raise DecodeError(f"Invalid header string: {e}") from e

Because the block only intercepts ValueError, a RecursionError is raised directly back to the caller. This behavior violates the PyJWT contract, which guarantees that all parsing and encoding anomalies are translated into a subclass of PyJWTError.

The patch remediates this issue by explicitly catching RecursionError alongside ValueError as shown in the diff below:

try:
    header: dict[str, Any] = json.loads(header_data)
except (ValueError, RecursionError) as e:
    raise DecodeError(f"Invalid header string: {e}") from e

This modification ensures that if stack exhaustion occurs during the JSON parsing phase, it is normalized to a standard DecodeError. Web frameworks and application controllers that rely on PyJWT to handle authentication can then gracefully catch DecodeError and issue a standard HTTP 401 or 403 status code.

Exploitation Methodology

Exploitation does not require high technical complexity. An attacker begins by constructing a malformed JSON payload containing deeply nested brackets. For example, an array nested within one thousand other arrays ([[[[...]]]]) is sufficient to exceed standard recursion limits.

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ ... ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

The attacker base64url-encodes this nested JSON string to generate the first token segment. They then append two arbitrary strings separated by periods, representing a dummy payload and a dummy signature. This constructs a well-formed compact JWS token layout containing a malicious header.

When the target web service receives the token, it forwards the string to PyJWT. PyJWT attempts to decode the header first. The parser exhausts the execution stack, raises a RecursionError, and crashes the thread. In asynchronous or multi-threaded environments, sending a steady stream of these payloads can exhaust the web server's available thread pool, inducing complete application unavailability.

Impact Assessment

The impact of this vulnerability is a remote, unauthenticated Denial of Service (DoS). Because the header is decoded prior to signature verification, the attacker does not need to possess a valid signing key, access token, or active session on the target application.

While the vulnerability does not allow remote code execution or data extraction, the operational cost of unhandled thread termination can be significant. High-performance web applications running on single-process event loops can experience severe latency spikes or temporary outages if the primary event handler is blocked or terminated.

This vulnerability has been assigned a CVSS v3.1 score of 5.3 (Medium). The vector string is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L. This reflects network-based availability impact with low attack complexity and no privilege requirements.

Remediation & Defense-in-Depth

The primary remediation is upgrading PyJWT to version 2.14.0 or higher. This version implements the revised exception handling wrapper, converting the raw RecursionError into a library-controlled DecodeError.

For systems where upgrading PyJWT is not immediately viable, a defense-in-depth approach can be deployed. Web application firewalls (WAFs) should be configured to inspect authorization headers and block request parameters containing repeating arrays or dictionary characters before they reach the application interpreter.

Additionally, developers can implement a middleware check that measures the length and structural nesting of the header segment before calling PyJWT. If a token contains more than 50 opening bracket characters, the middleware can reject the transaction outright.

Official Patches

jpadilla (GitHub Releases)PyJWT release containing the fix.

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 81% most exploited
15,000
via Censys & Shodan Framework Profiling

Affected Systems

Applications utilizing PyJWT versions between 2.13.0 (inclusive) and 2.14.0 (exclusive) for JWT validation.

Affected Versions Detail

Product
Affected Versions
Fixed Version
PyJWT
jpadilla
>= 2.13.0, < 2.14.02.14.0
AttributeDetail
CWE IDCWE-674 (Uncontrolled Recursion)
Attack VectorNetwork
CVSS Score5.3 (Medium)
EPSS Score0.00291 (0.29%)
Exploit StatusProof of Concept
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion Flood
Impact
CWE-674
Uncontrolled Recursion

The software implements a function that calls itself or relies on recursive parsing libraries without restricting the depth of recursion, allowing stack exhaustion.

Known Exploits & Detection

GitHub (PyJWT Test Suite)Official reproduction code confirming stack exhaustion via highly nested brackets.

Vulnerability Timeline

Vulnerability fixed in pyjwt git repository
2026-09-09
PyJWT version 2.14.0 released
2026-09-11
CVE-2026-102265 assigned and published
2026-09-28

References & Sources

  • [1]GitHub Security Advisory GHSA-8wjv-2p76-3863
  • [2]Fix Commit: Handle recursive JWS headers as decode errors
  • [3]CVE-2026-102265 Record (CVE.org)
  • [4]NVD CVE-2026-102265 Detail

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 1 hour ago•CVE-2026-101918
5.3

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

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.

Alon Barad
Alon Barad
4 views•5 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
5 views•7 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
•about 7 hours ago•CVE-2026-102276
7.5

CVE-2026-102276: Denial of Service via Uncontrolled Recursion and Argument-List Exhaustion in brace-expansion

CVE-2026-102276 is a high-severity Denial of Service (DoS) vulnerability impacting the 'brace-expansion' library, a popular Node.js utility designed to expand brace patterns into combinatorial lists. Due to uncontrolled recursion and argument-list stack exhaustion within the internal parseCommaParts function, remote attackers can trigger an unhandled RangeError that abruptly terminates the Node.js process.

Alon Barad
Alon Barad
9 views•7 min read