High priorityDisclosed

Advisory · CVE-2026-103262

Tornado's curl client had no size limit, so a 4 MB bomb ate a gigabyte

Tornado's CurlAsyncHTTPClient accumulated decompressed response bytes with no size accounting, letting a remote server OOM-kill the whole application with a small gzip bomb.

Vendor
Tornado
Product
Tornado
Identifier / CWE
CVE-2026-103262
CWE-409, CWE-400
Action timing
Immediate
ELI5

Explain it like I’m five

Tornado's delivery driver accepted packages without ever checking how big they were. A prankster mailed a tiny box that unfolded into a warehouse, and the truck burst.

SIMPLIFIED_ATTACK_PATH04 STEPS
  1. 01Curl client configured

    The application configures CurlAsyncHTTPClient, the documented choice for proxy support and advanced TLS options, and fetches an attacker-chosen or attacker-compromised URL with default decompression enabled.

  2. 02Bomb served

    The malicious server replies with a small gzip-encoded body carrying a Content-Encoding: gzip header.

  3. 03Silent decompression

    libcurl decompresses the response before the write callback, and every decompressed byte lands in an unbounded buffer with no size accounting, since the curl client never got the size gates added to the default client.

  4. 04Memory exhausted

    Process memory climbs linearly until the kernel OOM-kills the application, taking down every user the event loop was serving.

What happened

The Tornado security advisory GHSA-chx6-46f5-w4vp describes an unbounded memory accumulation flaw (CWE-409, CWE-400) in tornado.curl_httpclient.CurlAsyncHTTPClient. When an application used the curl client and fetched a remote URL with default decompression enabled, a malicious server could reply with a small gzip-encoded response that expanded without limit in the client’s memory buffer.

The curl client path contained no response-size accounting at all: the size gates that protect the default SimpleAsyncHTTPClient were never plumbed into it. Researchers demonstrated a roughly 4 MB wire payload driving a 1 GiB process to an OOM kill in about three seconds. Because the accumulation happens on the shared event loop’s client, one malicious response takes down the entire application. The issue affects Tornado versions before 6.5.9 and is fixed in 6.5.9.

What to do

  1. Upgrade to Tornado 6.5.9 or later.
  2. Inventory services that fetch attacker-influenced URLs, such as URL fetchers, webhook processors, link previewers, and feed pollers, especially those configured to use the curl client.
  3. Where upgrading must wait, avoid fetching untrusted URLs with the curl client and consider bounding response handling at the application layer.
  4. Monitor application memory for unexplained growth and OOM kills that could indicate probing.

Management note

A denial-of-service bug that needs no credentials and costs the attacker megabytes to inflict gigabytes of damage is the kind of thing that turns a link previewer into an outage. The fix is a one-line upgrade; the exposure audit is the part that takes an afternoon.