GHSA-R4J5-9XPP-3985

Vulnerability from github – Published: 2026-10-28 22:43 – Updated: 2026-10-28 22:43
VLAI
Summary
Tornado: Event loop blocking and excess memory use from chunked bodies with many small chunks
Details

Summary

When Tornado reads an HTTP/1.1 body that uses chunked transfer encoding, it processes all chunks that have already arrived without yielding to the event loop. A client can send a body made of millions of 1-byte chunks, which blocks the event loop (and therefore every other connection served by that process) for the entire time it takes to parse the body. A body near the default max_body_size of 100 MB can block the process for close to a minute, and the attacker can repeat or parallelize these requests.

Bodies made of tiny chunks also consumed far more memory than their size: a handler that does not use @stream_request_body stored each chunk as a separate object, using roughly 20 times as much memory as the bytes received.

Impact

All Tornado HTTP servers are affected when they receive a request body for a handler that reads it, which includes any handler that does not reject the request before the body is read. No authentication is required. Lowering max_body_size reduces the maximum blocking time and memory use for each request but does not remove the issue.

SimpleAsyncHTTPClient is affected in the same way when it reads a response from a malicious server.

Patches

Fixed in Tornado 6.6. Tornado now yields to the event loop periodically while reading any body, combines small chunks before passing them to data_received, and stores non-streaming bodies more compactly.

Applications using @stream_request_body should note that the pieces passed to data_received no longer correspond to HTTP chunk boundaries.

Workarounds

  • Run Tornado behind a reverse proxy that buffers request bodies and forwards them with a Content-Length header instead of chunked encoding.
  • Lower max_body_size (for the whole server or for individual handlers) to limit the impact of each request.

Credit

Reported by uttej-badwane.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "tornado"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-115927"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-770"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-28T22:43:50Z",
    "nvd_published_at": "2026-10-26T20:17:52Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\n\nWhen Tornado reads an HTTP/1.1 body that uses chunked transfer encoding, it processes all chunks that have already arrived without yielding to the event loop. A client can send a body made of millions of 1-byte chunks, which blocks the event loop (and therefore every other connection served by that process) for the entire time it takes to parse the body. A body near the default `max_body_size` of 100 MB can block the process for close to a minute, and the attacker can repeat or parallelize these requests.\n\nBodies made of tiny chunks also consumed far more memory than their size: a handler that does not use `@stream_request_body` stored each chunk as a separate object, using roughly 20 times as much memory as the bytes received.\n\n### Impact\n\nAll Tornado HTTP servers are affected when they receive a request body for a handler that reads it, which includes any handler that does not reject the request before the body is read. No authentication is required. Lowering `max_body_size` reduces the maximum blocking time and memory use for each request but does not remove the issue.\n\n`SimpleAsyncHTTPClient` is affected in the same way when it reads a response from a malicious server.\n\n### Patches\n\nFixed in Tornado 6.6. Tornado now yields to the event loop periodically while reading any body, combines small chunks before passing them to `data_received`, and stores non-streaming bodies more compactly.\n\nApplications using `@stream_request_body` should note that the pieces passed to `data_received` no longer correspond to HTTP chunk boundaries.\n\n### Workarounds\n\n- Run Tornado behind a reverse proxy that buffers request bodies and forwards them with a `Content-Length` header instead of chunked encoding.\n- Lower `max_body_size` (for the whole server or for individual handlers) to limit the impact of each request.\n\n### Credit\n\nReported by [uttej-badwane](https://github.com/uttej-badwane).",
  "id": "GHSA-r4j5-9xpp-3985",
  "modified": "2026-10-28T22:43:50Z",
  "published": "2026-10-28T22:43:50Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/tornadoweb/tornado/security/advisories/GHSA-r4j5-9xpp-3985"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-115927"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tornadoweb/tornado/pull/3773"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tornadoweb/tornado/commit/ceab33581489751a66fba8566ad6d5960d4b01c8"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/tornadoweb/tornado"
    },
    {
      "type": "WEB",
      "url": "https://github.com/tornadoweb/tornado/releases/tag/v6.6.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Tornado: Event loop blocking and excess memory use from chunked bodies with many small chunks"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline

Sightings and recorded dates, grouped by day · UTC

JSON
Events included in the timeline

Loading timeline…


    Loading…

    Loading…

    Loading…

    Related by attack behaviour

    Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.