VDB
Sign up
LOW

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`

Quick fix

GHSA-wwv5-g3v4-889x — tornado: upgrade to the fixed version with the command below.

pip install --upgrade 'tornado>=6.5.8'

Details

## 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).

Are you affected?

Enter the version of the package you're using.

Affected packages

PyPI/tornado
Introduced in: 6.5.5Fixed in: 6.5.8
Fixpip install --upgrade 'tornado>=6.5.8'

References