Skip to main content

Threat Intelligence Database

Comprehensive database of the latest cyber threats affecting organizations worldwide. Filter and search to find specific threat intelligence relevant to your organization.

Pro Console Lifetime

Stop chasing alerts. Route them.

Start free, then upgrade once to turn Radar into an automated delivery engine for your security stack.

Custom feeds / Automations: email, Slack, webhooks, SIEM/MISP / API access (baseline limits)

View Plans & Pricing

API access activates after upgrading in Console -> Billing.

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now

Filter Threats

Narrow down the results by type, severity, or affected countries

Search threats by title, CVE ID, or description. Maximum 100 characters.
Active filters (1):Package: pkg:pypi/tornado

Threat Intelligence

Click on any threat for detailed analysis and mitigation recommendations

CVE-2026-103263 is a high-severity vulnerability in Tornado's StaticFileHandler that allows unauthenticated attackers to read arbitrary files on the server by exploiting symbolic links within the static directory. The flaw arises because path validation uses os.path.abspath(), which does not resolve symlinks, allowing attackers to access files outside the intended directory. This can expose sensitive files such as configuration files, private keys, and application secrets. The vulnerability affects Tornado versions prior to 6.5.9.

Join the discussion

Tornado versions before 6.5.9 have a vulnerability in CurlAsyncHTTPClient where highly compressed gzip responses can cause unbounded memory accumulation. This can lead to denial of service by exhausting system memory and crashing the application process.

Join the discussion

## Summary `HTTPServerRequest.__init__` in `tornado/httputil.py` parses the URL query string via `parse_qs_bytes()` with no field-count limit — while the sibling POST-body parsing path (`parse_body_arguments`) received a `max_num_fields=1000` cap added earlier in this exact same release (v6.5.8, commit `8d6363ed`), explicitly to bound parsing cost for the identical underlying primitive. This leaves the query-string path with the resource-exhaustion exposure the body-path fix was meant to close. **File**: `tornado/httputil.py`, line 553 (`HTTPServerRequest.__init__`) ### Root Cause ```python # tornado/httputil.py:553 (before fix) self.arguments = parse_qs_bytes(self.query, keep_blank_values=True) ``` Compare with the POST-body path fixed one commit earlier in the same release: ```python # tornado/httputil.py:1038-1041 uri_arguments = parse_qs_bytes( body, keep_blank_values=True, max_num_fields=config.urlencoded.max_arguments, # default 1000 ) ``` Both call sites funnel through the same `tornado.escape.parse_qs_bytes` (a thin wrapper over `urllib.parse.parse_qs`), which is exactly why `max_num_fields` was added to `urllib.parse.parse_qsl` upstream — to let frameworks bound field count. The fix was applied only to the body path; the query-string path was missed. The request line + headers together are capped at `max_header_size` (default 65536 bytes), so this is not literally unbounded, but a single ~64KB request line can carry thousands of short `key=value` pairs — far beyond the 1000-field limit the maintainer judged appropriate for the structurally identical body case. ### Attack Scenario 1. Attacker sends a `GET` request whose query string is packed with thousands of short fields (e.g. `k0=1&k1=1&...&k7799=1`, ~61KB), fitting comfortably under `max_header_size`. No authentication, cookies, or prior state required. 2. Tornado accepts and parses this with no field-count cap, unlike the equivalent POST-body request (which is correctly rejected with 400 once >1000 fields are present). 3. Parsing thousands of fields is CPU work performed synchronously inside Tornado's single-threaded `IOLoop`. Several such requests in flight concurrently stall the event loop, delaying processing of *all* other connections on that loop — not just the attacker's own request. ### Verification (dynamic, local reproduction against v6.5.8) Ran the unmodified v6.5.8 source directly (no external dependencies needed) with a minimal `tornado.web.Application` on `127.0.0.1:8888`. - Identical 7800-field/~61KB payload sent as GET query string → `200 OK`; sent as POST body (`application/x-www-form-urlencoded`) → `400 Bad Request` (correctly rejected by the existing `max_num_fields` body-path limit). This confirms the asymmetry directly. - Per-request parse cost: baseline (`/?a=1`) averaged 1.86ms; the 7800-field query string averaged 25.1ms (~13x). - Event-loop-blocking amplification (raw-socket test, isolating server-side stall from client overhead): with 10 sequential baseline probe requests fired with no load, average latency was 1.47ms (max 5.9ms). With 5 concurrent 61KB/7800-field requests in flight, the same baseline probes averaged 13.0ms (max 118.1ms) — an **8.9x average slowdown** for unrelated clients, produced by ~305KB of unauthenticated attacker traffic. ### Impact All Tornado servers/applications are affected — this triggers on every request with a query string, independent of application/handler logic. An unauthenticated, unprivileged remote attacker can measurably degrade response times for all other clients sharing the same `IOLoop`, using a small amount of bandwidth and no special conditions. This is an availability/DoS concern; no confidentiality or integrity impact. ### Recommended Fix ```python # tornado/httputil.py — HTTPServerRequest.__init__ if uri is not None: self.path, sep, self.query = uri.partition("?") try: self.arguments = parse_qs_bytes( self.query, keep_blank_values=True, max_num_fields=_DEFAULT_PARSE_BODY_CONFIG.urlencoded.max_arguments, ) except ValueError as e: raise HTTPInputError("Invalid query string: %s" % e) from e ``` This reuses the existing `ParseUrlEncodedConfig.max_arguments` default (1000) via the module's `_DEFAULT_PARSE_BODY_CONFIG`, matching the POST-body limit and honoring any global override via `set_parse_body_config()`. The `try/except` is necessary because — unlike `parse_body_arguments`, which already wraps its call and converts `ValueError` into a clean `HTTPInputError`/400 — the query-string call site currently has no such handling, so without it, a request exceeding the limit would raise an uncaught `ValueError` instead of a clean 400. Verified: with the fix applied, requests with ≤1000 query-string fields are unaffected; requests with >1000 fields are rejected with `400 Bad Request` (consistent with the POST-body behavior); Tornado's own `httputil_test` and `web_test` suites (256

Join the discussion

CVE-2026-91992 is a vulnerability in Tornado's CurlAsyncHTTPClient (up to version 6.5.6) where per-request credentials such as client TLS certificates and proxy authentication credentials are not properly cleared when reusing curl handles. This causes sensitive information from one request to leak into subsequent requests made with the same client, potentially exposing credentials to unintended hosts. The issue affects all Tornado versions prior to 6.5.7.

Join the discussion

CVE-2026-91990 is a high-severity denial-of-service vulnerability in the Tornado web framework's multipart form data parsing. The function parse_multipart_form_data creates a large transient list by splitting the entire request body before checking the maximum allowed parts, leading to excessive memory use. This can be exploited by sending a specially crafted HTTP request with many parts, causing a pre-authentication denial of service.

Join the discussion

Tornado's CurlAsyncHTTPClient class is vulnerable to HTTP request/response splitting due to improper neutralization of CRLF sequences in HTTP headers. This allows an attacker to inject arbitrary headers or even additional HTTP requests if untrusted header values are used. The vulnerability arises because Tornado does not validate or reject CRLF characters in headers passed to libcurl, which sends them verbatim. This issue affects Tornado versions prior to 6.4.1 and has a medium severity rating.

Join the discussion

CVE-2024-14029 is a critical HTTP request smuggling vulnerability in Tornado web server versions prior to 6.4.1. It occurs when Tornado receives HTTP requests containing two Transfer-Encoding: chunked headers, causing it to ignore both and misinterpret the request body. This behavior can lead to request smuggling attacks when Tornado is deployed behind proxies that forward such malformed requests, such as Pound. The vulnerability may allow attackers to bypass access controls, poison caches, or cause connection desynchronization.

Join the discussion

Tornado versions from 6.5.5 up to but not including 6.5.8 contain an incomplete fix for cookie attribute injection. This vulnerability allows attackers to inject arbitrary cookie attributes by using capitalized or legacy keyword arguments in the set_cookie function. By embedding semicolon-delimited data in parameters such as Domain, Path, or SameSite, attackers can bypass validation and alter cookie security attributes. The issue is classified as an HTTP request/response splitting vulnerability related to improper neutralization of CRLF sequences in HTTP headers.

Join the discussion

Tornado's gzip decompression routines work in limited-size chunks, but have no overall limit for the total size of decompressed chunks that they will accumulate (There has always been a limit for the total *compressed* size). This allows a malicious server to consume effectively unlimited amounts of memory if it is accessed via SimpleAsyncHTTPClient in its default configuration. `HTTPServer` is not affected in its default configuration, but it is if `decompress_request=True` is set. This bug is fixed in Tornado 6.5.6. `max_body_size` is now checked both for the compressed and cumulative decompressed size of the response. Prior to upgrading, this issue can be mitigated by setting `decompress_response=False` or using `CurlAsyncHTTPClient`.

Join the discussion

### Summary Tornado's optional native extension `tornado.speedups` implements `websocket_mask` without validating that the `mask` argument is exactly four bytes long. The C function reads four bytes from `mask` unconditionally, even when Python passes a shorter byte string. This can read beyond the provided buffer, exposing up to 3 bytes of uninitialized memory. The behavior is reachable from Tornado's XSRF token decoder when `xsrf_cookies=True` and the native extension is active. ### Mitigations This bug is fixed in Tornado 6.5.6. Prior to upgrading to this version, setting the environment variable TORNADO_EXTENSION=0 will disable the vulnerable code (at the expense of reducing websocket performance).

Join the discussion

Showing 1 to 10 of 17 results

Filters:Package: pkg:pypi/tornado
Page 1 of 2
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses