Repository navigation
v5.1.1.post3
·
843 commits
to master
since this release
Security backport release for the Python 2.7-compatible tornado 5.1.1 line. It backports 18 advisories from Tornado 6.5.3–6.6.0. Each was checked against the 5.1.1 source: all 18 apply to 5.1.1 and all are fixed; none was assessed as not applicable. The release is cumulative: it includes every fix in 5.1.1.1 and 5.1.1+security.2.
Fixed
| Advisory | CVE | Fix |
|---|---|---|
| GHSA-pr2v-jx2c-wg9f | CVE-2025-67724 | Invalid HTTP reason phrases are replaced and escaped (header injection / XSS) |
| GHSA-c98p-7wgm-6p64 | CVE-2025-67725 | Linear-time repeated header lines (quadratic DoS) |
| GHSA-jhmp-mqwm-3gq8 | CVE-2025-67726 | Linear-time header parameter parsing (quadratic DoS) |
| GHSA-3x9g-8vmp-wqvf | CVE-2026-49853 | SimpleAsyncHTTPClient strips Authorization/Cookie/credentials on cross-origin redirects |
| GHSA-cx3h-4qpv-8hc9 | CVE-2026-49854 | tornado.speedups validates the websocket mask length (out-of-bounds read) |
| GHSA-mgf9-4vpg-hj56 | CVE-2026-49855 | max_body_size enforced on the decompressed size |
| GHSA-mpf4-983q-p7j4 | CVE-2026-82397 | 1000-argument limit on urlencoded bodies |
| GHSA-pw6j-qg29-8w7f | — | CurlAsyncHTTPClient resets curl handles before reuse (credential leak) |
| GHSA-8423-8fgw-73vq | — | Multipart part limit applied before splitting the body |
| GHSA-3hv7-mjh2-fv65 | — | 1000-argument limit on query strings |
| GHSA-c2m8-h5v5-343r | — | StaticFileHandler doesn't follow symlinks out of the static root (allowed_symlink_directory opts in) |
| GHSA-chx6-46f5-w4vp | — | CurlAsyncHTTPClient gains max_body_size (100MB) and a bounded streaming buffer |
| GHSA-wwv5-g3v4-889x | — | Every set_cookie keyword attribute is validated (capitalized kwargs bypass) |
| GHSA-c6v4-qj2h-f748 | — | set_cookie max_age goes through int() (attribute injection) |
| GHSA-pw9p-v7r6-gx4p | — | RedirectHandler substitutions can't change the scheme or host (open redirect) |
| GHSA-pcg2-g6cj-q92c | — | Obsolete header line folding is rejected (quadratic DoS) |
| GHSA-r4j5-9xpp-3985 | — | Body reading yields to the IOLoop and coalesces tiny chunks (event-loop starvation) |
| GHSA-v8g8-cp5j-42fg | — | static_url validates paths, reads only regular files, caps size, and bounds its cache |
Other security improvements (no advisory)
max_body_sizeis enforced on read-until-close responses.- At most 10
1xxresponses are accepted. - A gzip body with trailing data no longer hangs the IOLoop.
- Multi-member gzip is decoded in full, and truncated gzip is rejected.
- Websocket reads yield to the IOLoop, and only the latest ping is answered.
- Valueless header parameters (
*_no_context_takeover) are honored.
Behavior changes
Most of these fixes reject input that was previously accepted:
- Folded headers get a 400 or 599.
- More than 1000 query or body arguments are rejected.
- The curl client refuses responses over 100MB decompressed.
- Symlinks out of the static root get a 403.
static_url("../x")raises a 403.- Trailing or truncated gzip is rejected.
data_receivedpieces no longer follow chunk boundaries.
CurlAsyncHTTPClient needs libcurl ≥ 7.81, and ≥ 7.83.0 for CVE-2026-49853 redirect stripping. Full details are in docs/releases/v5.1.1.post3.rst.
Verification
Tested on Python 2.7.18 with tornado.speedups built, and with pycurl 7.43.0.5 against libcurl 8.17.0:
- The targeted suite passes: 820 tests, 10 skipped.
- The sdist and wheel metadata say
5.1.1.post3.