Jul 20, 2026·6 min read·8 visits
Tornado web framework versions before 6.5.3 use an inefficient algorithm to parse header values, allowing unauthenticated remote attackers to cause a complete Denial of Service via CPU exhaustion with a single crafted request.
A denial of service vulnerability in Tornado versions 6.5.2 and below arises from excessive iteration in its parameter parser. The `_parseparam` function in `httputil.py` parses parameters in HTTP headers using an inefficient nested loop that counts double quotes from index zero. This implementation exposes a quadratic $O(n^2)$ complexity curve when processing quoted headers containing a high volume of semicolons, leading to CPU exhaustion and blocking the asynchronous event loop.
Tornado is an asynchronous Python web framework and networking library designed to handle thousands of simultaneous connections. The framework processes incoming HTTP requests, extracting metadata from headers such as Content-Disposition and Content-Type. During parameter parsing, Tornado uses an internal utility function called _parseparam within tornado/httputil.py. This function identifies and separates parameter key-value pairs separated by semicolons.
Because the parsing occurs on the synchronous side of the connection handler, any delay during header ingestion blocks the execution flow. The vulnerability described as CVE-2025-67726 represents an uncontrolled resource consumption issue (CWE-400) originating from excessive iteration (CWE-834). An attacker can supply a payload that forces the parser into a nested loop with quadratic complexity, causing the single-threaded event loop to freeze.
The vulnerability is located in the _parseparam function in tornado/httputil.py. When a multipart header contains parameters, they are separated by semicolons. Semicolons inside quoted strings (e.g., name="val;ue") must be ignored and not treated as parameter delimiters. To handle this, the parser searches for the next semicolon and checks if it falls inside an active quote context.
The parser calculates whether a quote is open by counting the total number of quotes and escaped quotes from the start of the string up to the found semicolon using s.count('"', 0, end) - s.count('\\"', 0, end). If this count is odd, the quote is open, and the parser advances to search for the next semicolon. When a single quoted parameter contains thousands of semicolons, the parser loops over each one, repeatedly counting quotes starting from index 0 up to the current semicolon index end.
This implementation results in quadratic time complexity $O(n^2)$ relative to the number of semicolons. As the number of semicolons increases, the parser takes exponentially longer to process the header. Furthermore, the parser repeatedly performs string slicing operations (s = s[end:]), which adds significant memory allocation and string-copying overhead to the CPU-bound operation.
The vulnerable code path from versions 6.5.2 and below demonstrates the recursive string slicing and full-prefix quote scanning:
# Vulnerable implementation in tornado/httputil.py (<= 6.5.2)
def _parseparam(s: str) -> Generator[str, None, None]:
while s[:1] == ";":
s = s[1:]
end = s.find(";")
# Scanning the entire prefix (0 to end) on each iteration
while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
end = s.find(";", end + 1)
if end < 0:
end = len(s)
f = s[:end]
yield f.strip()
s = s[end:]The fix introduced in version 6.5.3 replaces string slicing with index pointers and optimizes the quote counting to use a sliding window, converting the algorithm to linear time complexity $O(n)$:
# Patched implementation in tornado/httputil.py (6.5.3)
def _parseparam(s: str) -> Generator[str, None, None]:
start = 0
while s.find(";", start) == start:
start += 1
end = s.find(";", start)
ind, diff = start, 0
while end > 0:
# Sliding window count: only count quotes between ind and end
diff += s.count('"', ind, end) - s.count('\\"', ind, end)
if diff % 2 == 0:
break
# Typo: end and ind are updated, but note the order
end, ind = ind, s.find(";", end + 1)
if end < 0:
end = len(s)
f = s[start:end]
yield f.strip()
start = endAlthough the patch contains a logical permutation typo in end, ind = ind, s.find(";", end + 1), the performance remains robust and linear. Because Python's s.count is optimized in C, avoiding repeated scanning from index 0 successfully eliminates the quadratic complexity curve.
Exploitation of CVE-2025-67726 requires only network access to an endpoint that accepts multipart form uploads or parses user-supplied headers. An attacker can construct a payload where a header, such as Content-Disposition, includes a parameter with a long quoted string populated entirely with semicolons. The structure of the malicious request conforms to standard multipart forms, ensuring it bypasses basic structure validation filters.
When the Tornado server reads the multipart payload, it invokes parse_multipart_form_data which in turn calls _parseparam. The event loop blocks synchronously. Because Tornado's execution model is single-threaded and relies on a non-blocking event loop, blocking the main thread for even a few seconds halts all concurrent requests. An attacker sending multiple requests of this type can keep a multi-core server permanently unresponsive.
The impact of this vulnerability is assessed as high (CVSS 7.5). Because Tornado is frequently used to build high-performance APIs and WebSocket endpoints, a complete lockup of the single-threaded event loop results in immediate application failure. Connection pools are exhausted, existing client connections time out, and health-checks fail, prompting automated orchestrators like Kubernetes to restart the container.
There is no confidentiality or integrity impact associated with this flaw, as it does not allow memory corruption or remote code execution. However, the low barrier to entry and the minimal network resources required to execute the attack make it highly effective. A single client connection using negligible bandwidth can incapacitate a service running on substantial infrastructure.
The primary and recommended solution is upgrading the Tornado framework to version 6.5.3 or later. This release incorporates the index-based parsing method that prevents quadratic processing time. If updating the package is not immediately viable, temporary web application firewall (WAF) rules or reverse proxy limits should be deployed.
WAFs should be configured to limit the maximum length of individual HTTP headers to a reasonable limit (e.g., 1024 characters) and inspect headers for abnormally high densities of delimiters. For example, Nginx can be configured to drop requests with excessively large header buffer sizes. Developers can also implement intermediate middleware to strip or inspect headers before they reach Tornado's default parser core.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Tornado Tornado | < 6.5.3 | 6.5.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-834 / CWE-400 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00378 |
| Exploit Status | Proof of Concept |
| Impact | Denial of Service (DoS) |
| Remediation | Upgrade to Tornado v6.5.3 |
The application consumes excessive CPU resources by looping an uncontrolled or poorly managed number of times.
CVE-2026-59205 is a high-severity heap-based out-of-bounds write vulnerability affecting Pillow prior to version 12.3.0. The flaw stems from a validation omission in the ImageCmsTransform class where source and destination image modes are not checked against the configurations defined during the creation of the transform. An attacker can exploit this discrepancy to trigger a heap buffer overflow or an out-of-bounds read by supplying an under-allocated target image buffer.
A vulnerability in the 'body-parser' Node.js middleware allows unauthenticated attackers to trigger a Denial of Service. When the 'limit' configuration option is misconfigured with an unparseable type or empty value, size limits fail open. This leads to unrestricted heap memory allocation and process crash via Out of Memory (OOM).
A security vulnerability in @astrojs/netlify allows attackers to bypass remote image path restrictions by leveraging unescaped regular expression metacharacters. The integration adapter fails to sanitize developer-defined pathnames before interpolating them into a configuration JSON file consumed by Netlify's Edge Image CDN. This results in overly permissive matching behavior at the edge routing layer, enabling path-traversal and filter bypasses.
Prior to version 1.2.11, the LangChain LLM framework is affected by a Server-Side Request Forgery (SSRF) vulnerability inside its image token counting mechanism. Specifically, the ChatOpenAI.get_num_tokens_from_messages() method retrieves arbitrary image_url values from user prompts without validating the destination host or IP address. Attackers can exploit this issue to scan internal infrastructure, access local services, or harvest credentials from cloud metadata services.
A security vulnerability was identified in the Astro web framework's composable integration pipeline with Hono. Due to the structural coupling of CSRF origin validation exclusively within the `middleware()` primitive, applications assembling their routing pipeline manually could execute state-mutating actions before or entirely without origin validation. This flaw allows attackers to execute blind, write-only Cross-Site Request Forgery (CSRF) attacks against state-mutating Astro Actions or endpoints on behalf of authenticated users.
Multiple cross-site request forgery (CSRF) vulnerabilities in the HTTP Administration component in Cisco IOS 12.4 on the 871 Integrated Services Router allow remote attackers to execute arbitrary commands via crafted HTTP requests. This occurs because the web administrative server fails to validate request origins or use anti-CSRF tokens, allowing an attacker to abuse an active administrative session.