GitHub Advisoryadvisory · PyPI

GHSA-wwv5-g3v4-889x Tornado: Incomplete fix for CVE-2026-35536: cookie attribute injection re-opened via the legacy case-insensitive `**kwargs` path in `set_cookie`

LOW Published 2026-09-01 Modified 2026-09-01 Official page ↗
Ecosystem
PyPI
Packages
tornado
Severity
Low
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
Weaknesses
CWE-74
Reviewed
2026-09-01

Affected packages

• PyPI tornado: >= 6.5.5, < 6.5.8 → fixed in 6.5.8

Description

Summary The CVE-2026-35536 fix added a validation loop that rejects `[\x00-\x20\x3b\x7f]`, but only for the hardcoded lowercase keys `name`/`domain`/`path`/`samesite`. The still-live deprecated `kwargs` path writes attacker-supplied attribute values straight into the `Morsel` with no validation, and because `Morsel.__setitem__` is case-insensitive, a capitalized kwarg (`Domain=`, `Path=`, `SameSite=`, `Max-Age=`) routes to the same reserved attribute while bypassing the loop — re-opening `;`-delimited attribute injection. ```python self.set_cookie("sid", "abc", Domain="evil.com; Secure; SameSite=None") -> Set-Cookie: sid=abc; Domain=evil.com; Secure; SameSite=None; Path=/ Sanity (the canonical lowercase named arg IS blocked): self.set_cookie("sid", "abc", domain="evil.com; Secure") # -> http.cookies.CookieError ``` The patch's regression test (`SetCookieForbiddenCharHandler`) only exercises the four named params, never the `kwargs` path, so the gap is not regression-covered. Affected code • `tornado/web.py` → `RequestHandler.set_cookie`: the validation loop covers only the lowercase named args; the trailing `if kwargs:` loop does `morsel[k] = v` with no character validation. Steps to reproduce `GET /upper` (uses `Domain=` kwarg) emits `Set-Cookie: c_upper=v; Domain=evil.com; Secure; SameSite=None; Path=/`; `GET /lower` (uses lowercase `domain=`) returns a `CookieError`. Impact Injection of independent cookie attributes (force/drop `Secure`/`HttpOnly`/`SameSite`, rebind `Domain`/`Path`) — the same impact CVE-2026-35536 closed, via the sibling path the patch missed. Conditional on the app using a capitalized/legacy keyword. Suggested remediation Apply the same `[\x00-\x20\x3b\x7f]` validation to every entry in the `**kwargs` loop (after normalizing the key case), or remove the deprecated kwargs path; add a regression test for capitalized kwargs. Credit Reported as part of an incomplete-patch measurement study (responsible disclosure).

Related

Weakness · CWE (1)

  • CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component weakness

References