CVE-2025-67724: Tornado vulnerable to Header Injection and XSS via reason argument
Header injection and XSS via reason argument
Summary
The reason argument (used by both RequestHandler.setstatus and tornado.web.HTTPError is designed to allow applications to pass custom "reason" phrases (the "Not Found" in HTTP/1.1 404 Not Found) to the HTTP status line (mainly for non-standard status codes). Vulnerabilities exist in Tornado versions prior to 6.5.3 if untrusted data is passed as the reason argument.
Details
In vulnerable versions, the supplied reason phrase is used unescaped in HTTP headers (where it could be used for header injection) or in HTML in the default error page (where it could be used for XSS).
Impact
Type: Reflected Cross-Site Scripting (CWE-79) in default error page, or header injection (CWE-644) Actors: Remote attacker who can cause the application to raise HTTPError/setstatus with an attacker-controlled reason (e.g., via query parameter used by developer). Effect: Execution of arbitrary JavaScript in victims' browsers when they view the error page — possible session token theft, CSRF escalation, UI spoofing, or other client-side attacks depending on context. Scope: Only applications that explicitly reflect untrusted input into reason are affected.
Mitigation
Aside from upgrading to Tornado 6.5.3 or newer, the vulnerability can be mitigated by not using untrusted data for the reason argument. In the intended use case the reason argument would generally be a string literal and not derived from user input. Also, the reason argument is rarely required (reason phrases are not used at all in HTTP/2) and can generally be omitted.
For a general-purpose error message in HTTPError, consider using the logmessage argument instead of reason.
Other sources
Tornado is a Python web framework and asynchronous networking library. In versions 6.5.2 and below, the supplied reason phrase is used unescaped in HTTP headers (where it could be used for header injection) or in HTML in the default error page (where it could be used for XSS) and can be exploited by passing untrusted or malicious data into the reason argument. Used by both RequestHandler.setstatus and tornado.web.HTTPError, the argument is designed to allow applications to pass custom "reason" phrases (the "Not Found" in HTTP/1.1 404 Not Found) to the HTTP status line (mainly for non-standard status codes). This issue is fixed in version 6.5.3.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/tornadoto a version that resolves this vulnerability.Fixed in 6.5.3 - Upgrade
Upgrade
tornadoto a version that resolves this vulnerability.Fixed in 6.5.3 - Configuration
Mitigate by ensuring the `reason` argument passed to `tornado.web.HTTPError` and `RequestHandler.set_status` is not derived from untrusted input; prefer a string literal or omit the `reason` value.
Tornado HTTPError / RequestHandler.set_status reason argument = Do not use untrusted/user-controlled data (use a string literal or omit it)
Event History
Frequently Asked Questions
What is the severity of CVE-2025-67724?
CVE-2025-67724 has a high severity rating due to the risk of header injection and XSS vulnerabilities.
How do I fix CVE-2025-67724?
To fix CVE-2025-67724, upgrade to Tornado version 6.5.3 or later.
What systems are affected by CVE-2025-67724?
CVE-2025-67724 affects Tornado versions 6.5.2 and below.
What types of vulnerabilities are present in CVE-2025-67724?
CVE-2025-67724 includes header injection vulnerabilities and potential XSS in the default error page.
Is there a workaround for CVE-2025-67724?
There is no official workaround recommended; the best protection is to upgrade to a secure version.