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



GHSA-8423-8FGW-73VQ

GHSA-8423-8FGW-73VQ: Memory Amplification Denial of Service in Tornado Multipart Form Parser

Alon Barad
Alon Barad
Software Engineer

Sep 2, 2026·6 min read·13 visits

Executive Summary (TL;DR)

Unauthenticated remote Denial of Service in Tornado's multipart parser due to memory and CPU amplification occurring before verification of max_parts limits, leading to Out-of-Memory crashes.

GHSA-8423-8FGW-73VQ is a pre-authentication denial of service vulnerability in the Tornado web server's handling of multipart/form-data. The flaw allows an unauthenticated remote attacker to cause memory exhaustion and CPU starvation by transmitting a crafted HTTP request containing a high density of boundary delimiters. Because Tornado splits the entire request body in memory prior to enforcing the max_parts validation threshold, the Python interpreter attempts to materialize a massive list of byte segments. This triggers an immediate memory exhaustion (OOM) crash or server-wide CPU starvation before the payload can be validated and rejected.

Vulnerability Overview

The Tornado web framework utilizes the parse_multipart_form_data function inside its httputil module to process incoming multipart/form-data payloads. This function is exposed across any endpoint accepting file uploads or complex multi-part forms. The primary task of this parser is to segment the raw HTTP request body into discrete, manageable blocks using a boundary delimiter string supplied in the Content-Type header.

To safeguard against resource exhaustion attacks, Tornado permits administrators to enforce a max_parts constraint, which defaults to 1000. Under normal conditions, requests exceeding this threshold are immediately rejected. However, a structural control flow issue exists because the parser completes the partitioning of the entire input buffer before verifying the number of resulting segments against the configured limit.

An attacker can exploit this operational sequence by crafting a payload containing a extremely dense distribution of boundary delimiters. By utilizing a single-character boundary string, the attacker forces the underlying Python engine to execute a complete buffer split and allocate millions of individual transient byte slices. This allocation occurs in the pre-validation phase, consuming all available system memory and causing process termination.

Root Cause Analysis

The underlying technical flaw lies in the algorithmic execution order of tornado.httputil.parse_multipart_form_data. When a client initiates a multipart request, Tornado reads the raw byte stream and searches for the terminal boundary indicator using a reverse search (rfind). Once identified, the engine invokes Python's native bytes.split() method to partition the input stream.

Python's built-in bytes.split() executes a linear scan of the entire target memory buffer to locate all instances of the specified delimiter. For every match found, CPython allocates a new byte slice object and appends its reference to a dynamically growing list. This intensive memory allocation phase occurs entirely within the runtime environment before control returns to Tornado's validation logic.

Because the list is fully materialized in-memory before Tornado checks the number of components, the protection mechanism is bypassed during the critical allocation phase. A small 600KB request body containing 100,000 artificial boundaries will force the system to instantiate 100,000 distinct list items. If scaled to a larger payload such as 100MB, the system attempts to process roughly 17.5 million list elements, leading to a complete depletion of system RAM.

Code Analysis

The vulnerable logic is located within tornado/httputil.py. In affected versions, the parsing sequence was structured as follows:

# Vulnerable code path in affected versions of tornado/httputil.py
def parse_multipart_form_data(
    boundary: bytes, data: bytes, arguments: Dict[str, List[bytes]], files: Dict[str, List[ObjectDict]], config: Optional[HttpRequestConfig] = None
) -> None:
    ...
    final_boundary_index = data.rfind(b"--" + boundary + b"--")
    if final_boundary_index == -1:
        raise HTTPInputError("Invalid multipart/form-data: no final boundary found")
    
    # Vulnerable split operation: processes entire stream with no limit
    parts = data[:final_boundary_index].split(b"--" + boundary + b"\r\n")
    
    # Limit validation: occurs after memory has already been exhausted
    if len(parts) > config.max_parts:
        raise HTTPInputError("multipart/form-data has too many parts")

The vulnerability was resolved in commit de85b3f87446e323e881bbaa3d5a74f4b76e5f05 by passing an explicit limit to the split() function:

# Patched code path in tornado/httputil.py
    # The split depth is restricted to config.max_parts + 1
    parts = data[:final_boundary_index].split(
        b"--" + boundary + b"\r\n", config.max_parts + 1
    )

By specifying config.max_parts + 1 as the maxsplit parameter, the Python interpreter halts the buffer scan and terminates partitioning immediately after reaching the limit. The remaining unparsed segment is left intact as the final entry in the list, ensuring that total list allocations never exceed config.max_parts + 2 elements. This hard ceiling prevents uncontrolled heap consumption.

Attack Methodology and Proof-of-Concept

Exploitation of GHSA-8423-8FGW-73VQ requires no authentication and can be completed through a single crafted HTTP POST request. The attacker targets any application route configured to handle multipart form submissions. To maximize amplification efficiency, the attacker overrides the multipart boundary parameter in the Content-Type header to a single character, such as x.

The attacker then generates a payload containing a dense sequence of delimiter bytes. For a boundary designated as x, the required delimiter search pattern is b"--" + b"x" + b"\r\n". A single arbitrary byte is positioned between each delimiter, creating a highly compressed payload:

POST /upload HTTP/1.1
Host: target-server.local
Content-Type: multipart/form-data; boundary=x
Content-Length: 600005
 
q--x
q--x
... [repeated 100,000 times] ...
--x--

When the Tornado parser encounters this payload, the built-in split() method executes and instantly materializes 100,000 Python byte slice objects. Under concurrent conditions, or when scaled to larger request sizes, the rapid surge in memory allocations exhausts the host's physical RAM, forcing the operating system kernel's Out-of-Memory (OOM) killer to terminate the web server process.

Impact Assessment

The operational impact of this vulnerability is a complete Denial of Service (DoS) affecting web application availability. Because Tornado relies on an asynchronous, single-threaded event loop structure, blocking operations or process crashes immediately terminate service for all active and pending client connections.

While this issue does not facilitate remote code execution or expose sensitive application data, it represents a highly effective disruption vector. In containerized environments such as Docker or Kubernetes, the depletion of container memory limits will trigger automatic pod restarts, leading to a continuous state of instability if the attack is sustained.

No specialized exploitation tools or privileges are needed to launch this attack. The presence of public proof-of-concept scripts combined with the pre-authentication nature of the vulnerability creates a low barrier to entry for prospective threat actors seeking to degrade service availability.

Remediation and Mitigation Guidance

The recommended remediation path is to upgrade Tornado to version 6.5.8 or higher. This version implements the restricted maxsplit logic, preventing memory amplification.

If immediate upgrading is not possible, security teams should implement perimeter defensive controls. Web Application Firewalls (WAFs) or reverse proxies (such as Nginx) can be configured to block requests that contain suspiciously short boundary strings in the Content-Type header. Standard browsers generate long, random boundary hashes, so rejecting boundaries shorter than 8 characters is a safe and reliable filter.

# Example Nginx configuration to restrict request body sizes on upload endpoints
client_max_body_size 2M;

Additionally, restricting the maximum permitted body size for multipart requests limits the raw volume of delimiters an attacker can submit, effectively capping the potential amplification factor.

Official Patches

TornadoOfficial patch implementing early restriction on split limits in httputil.py

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N

Affected Systems

Tornado Web Server

Affected Versions Detail

Product
Affected Versions
Fixed Version
tornado
tornadoweb
< 6.5.86.5.8
AttributeDetail
CWE IDCWE-400
Attack VectorNetwork
CVSS Score5.3
EPSS ScoreNot Available
ImpactDenial of Service (DoS)
Exploit StatusPoC Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion Flood
Impact
CWE-400
Uncontrolled Resource Consumption

The program does not properly control the allocation and maintenance of a key resource, allowing an actor to construct a request designed to consume excessive resources.

Known Exploits & Detection

GitHub GistProof of Concept script demonstrating memory amplification via the split-before-count vulnerability in Tornado's httputil parser.

Vulnerability Timeline

Proof of Concept exploit published on GitHub Gist by researcher afldl.
2026-07-31
Official patch committed to the Tornado repository by maintainer Ben Darnell.
2026-08-05
Tornado version 6.5.8 released containing the security fix.
2026-09-01
Security advisory GHSA-8423-8fgw-73vq published to the GitHub Advisory Database.
2026-09-01

References & Sources

  • [1]GHSA-8423-8fgw-73vq Security Advisory
  • [2]Tornado Fix Commit
  • [3]Tornado Release v6.5.8
  • [4]Exploit Proof of Concept Gist

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 16 hours ago•CVE-2026-11748
6.9

CVE-2026-11748: Unauthenticated LDAP Injection in Central Dogma Server Authentication

An LDAP injection vulnerability exists in the centraldogma-server-auth-shiro module of LY Corporation Central Dogma before version 0.84.0. The search logic dynamically constructs LDAP search filters by interpolating user-provided usernames without escaping RFC 4515 metacharacters. Unauthenticated remote attackers can leverage this flaw to bypass authentication, enumerate directory hierarchies, and access unauthorized resources.

Alon Barad
Alon Barad
7 views•6 min read
•about 17 hours ago•CVE-2026-11746
9.4

CVE-2026-11746: Use of Hard-coded ZooKeeper Replication Secret 'ch4n63m3' in Central Dogma Server

CVE-2026-11746 is a critical vulnerability in Central Dogma Server prior to version 0.84.0, where an embedded ZooKeeper replication secret silently falls back to a publicly known, hard-coded default string ('ch4n63m3'). Remote attackers with access to the replication network can authenticate as legitimate cluster peers, potentially leading to unauthorized data exposure, state manipulation, or complete cluster takeover.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 18 hours ago•CVE-2026-56665
4.2

CVE-2026-56665: Logical Validation Bypass in ZITADEL External JWT Identity Provider

A logical verification flaw in ZITADEL's external JWT Identity Provider validation allows attackers to bypass session expiration checks. If an incoming JWT lacks the 'exp' claim, the system skips validation entirely, creating an indefinitely valid session. This issue has been addressed in versions 3.4.12 and 4.15.2.

Alon Barad
Alon Barad
4 views•7 min read
•about 19 hours ago•CVE-2026-59149
6.5

CVE-2026-59149: Sibling Directory Path Traversal in Mockoon Backend Server

CVE-2026-59149 identifies a directory traversal vulnerability in `@mockoon/commons-server`, the backend mock-server library powering the Mockoon application. The flaw occurs in the path containment validation logic used during raw file response generation. An unauthenticated attacker can exploit this weakness to retrieve arbitrary files from sibling directories sharing a common prefix with the designated static base directory.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 20 hours ago•CVE-2026-59148
8.8

CVE-2026-59148: Unauthenticated Administrative API and CORS Misconfiguration in Mockoon

An in-depth analysis of CVE-2026-59148, a high-severity flaw in Mockoon where unauthenticated administrative endpoints and a wildcard Cross-Origin Resource Sharing (CORS) policy allow remote execution, state poisoning, and credential theft.

Alon Barad
Alon Barad
5 views•6 min read
•about 21 hours ago•CVE-2026-56666
4.8

CVE-2026-56666: Account Takeover via Improper Email Verification in ZITADEL Federated Identity Handler

An improper authentication vulnerability (CWE-287) in ZITADEL's external identity provider handler before version 4.15.3 allows remote attackers to perform complete account takeover. When auto-linking by email is enabled, ZITADEL verifies that the local target account has a verified email address but fails to verify if the external provider confirmed ownership of that same email. Attackers can exploit this by registering an unverified account with a victim's email address on a permissive external provider, leading to unauthorized account binding and persistent access.

Amit Schendel
Amit Schendel
2 views•7 min read