Executive brief
Tornado's HTTP client implementation reuses network connections across requests but fails to clear sensitive authentication state between them. An attacker who can influence multiple requests through the same client instance can steal TLS certificates, proxy credentials, or force requests through unintended network interfaces. This is a serious risk in multi-tenant or proxy-based deployments where credentials should be isolated per-request.
Technical details
CurlAsyncHTTPClient in tornado/curl_httpclient.py pools and reuses pycurl handles for performance, but _curl_setup_request() does not call curl.reset() between requests. Per-request options like SSLCERT, SSLKEY, PROXYUSERPWD, and INTERFACE are set conditionally and lack corresponding unset/clear branches, causing sensitive state from one request to leak into subsequent requests on the same client instance. Attack vectors include: (A) client TLS certificate persistence allowing an attacker's request to present the certificate during TLS handshake to an unintended host, and (B) proxy authentication credentials persisting and being sent to a different proxy. No user interaction or authentication is required; the vulnerability is triggered by issuing multiple HTTP requests through a shared client instance. Tornado 6.5.7 patches this by properly resetting pycurl handles between requests.
Affected products
- Tornado Tornado before 6.5.7
Timeline
- 2026-06-08: disclosed: GitHub Security Advisory GHSA-pw6j-qg29-8w7f published
- 2026-06-08: patched: Fixed in Tornado 6.5.7
- 2026-09-15: advisory: NVD entry published