mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-06-14 05:49:57 +00:00
python3-tornado: fix CVE-2026-35536
Backport the commit[1] from version 6.5.5 which fixes this vulnerability according to the NVD[2]. [1] https://github.com/tornadoweb/tornado/commit/24a2d96ea115f663b223887deb0060f13974c104 [2] https://nvd.nist.gov/vuln/detail/CVE-2026-35536 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
From 66587e51009457274cedec28f5fd43000d129e4e Mon Sep 17 00:00:00 2001
|
||||
From: Ben Darnell <ben@bendarnell.com>
|
||||
Date: Fri, 6 Mar 2026 14:50:25 -0500
|
||||
Subject: [PATCH] web: Validate characters in all cookie attributes.
|
||||
|
||||
Our previous control character check was missing a check for
|
||||
U+007F, and also semicolons, which are only allowed in quoted
|
||||
parts of values. This commit checks all attributes and
|
||||
updates the set of disallowed characters.
|
||||
|
||||
CVE: CVE-2026-35536
|
||||
Upstream-Status: Backport [https://github.com/tornadoweb/tornado/commit/24a2d96ea115f663b223887deb0060f13974c104]
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
tornado/test/web_test.py | 65 ++++++++++++++++++++++++++++++++++++++++
|
||||
tornado/web.py | 27 +++++++++++++++--
|
||||
2 files changed, 89 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py
|
||||
index 801a80ed..ae39e8fc 100644
|
||||
--- a/tornado/test/web_test.py
|
||||
+++ b/tornado/test/web_test.py
|
||||
@@ -1,3 +1,5 @@
|
||||
+import http
|
||||
+
|
||||
from tornado.concurrent import Future
|
||||
from tornado import gen
|
||||
from tornado.escape import (
|
||||
@@ -291,11 +293,67 @@ class CookieTest(WebTestCase):
|
||||
self.set_cookie("unicode_args", "blah", domain="foo.com", path="/foo")
|
||||
|
||||
class SetCookieSpecialCharHandler(RequestHandler):
|
||||
+ # "Special" characters are allowed in cookie values, but trigger special quoting.
|
||||
def get(self):
|
||||
self.set_cookie("equals", "a=b")
|
||||
self.set_cookie("semicolon", "a;b")
|
||||
self.set_cookie("quote", 'a"b')
|
||||
|
||||
+ class SetCookieForbiddenCharHandler(RequestHandler):
|
||||
+ def get(self):
|
||||
+ # Control characters and semicolons raise errors in cookie names and attributes
|
||||
+ # (but not values, which are tested in SetCookieSpecialCharHandler)
|
||||
+ for char in list(map(chr, range(0x20))) + [chr(0x7F), ";"]:
|
||||
+ try:
|
||||
+ self.set_cookie("foo" + char, "bar")
|
||||
+ self.write(
|
||||
+ "Didn't get expected exception for char %r in name\n" % char
|
||||
+ )
|
||||
+ except http.cookies.CookieError as e:
|
||||
+ if "Invalid cookie attribute name" not in str(e):
|
||||
+ self.write(
|
||||
+ "unexpected exception for char %r in name: %s\n"
|
||||
+ % (char, e)
|
||||
+ )
|
||||
+
|
||||
+ try:
|
||||
+ self.set_cookie("foo", "bar", domain="example" + char + ".com")
|
||||
+ self.write(
|
||||
+ "Didn't get expected exception for char %r in domain\n"
|
||||
+ % char
|
||||
+ )
|
||||
+ except http.cookies.CookieError as e:
|
||||
+ if "Invalid cookie attribute domain" not in str(e):
|
||||
+ self.write(
|
||||
+ "unexpected exception for char %r in domain: %s\n"
|
||||
+ % (char, e)
|
||||
+ )
|
||||
+
|
||||
+ try:
|
||||
+ self.set_cookie("foo", "bar", path="/" + char)
|
||||
+ self.write(
|
||||
+ "Didn't get expected exception for char %r in path\n" % char
|
||||
+ )
|
||||
+ except http.cookies.CookieError as e:
|
||||
+ if "Invalid cookie attribute path" not in str(e):
|
||||
+ self.write(
|
||||
+ "unexpected exception for char %r in path: %s\n"
|
||||
+ % (char, e)
|
||||
+ )
|
||||
+
|
||||
+ try:
|
||||
+ self.set_cookie("foo", "bar", samesite="a" + char)
|
||||
+ self.write(
|
||||
+ "Didn't get expected exception for char %r in samesite\n"
|
||||
+ % char
|
||||
+ )
|
||||
+ except http.cookies.CookieError as e:
|
||||
+ if "Invalid cookie attribute samesite" not in str(e):
|
||||
+ self.write(
|
||||
+ "unexpected exception for char %r in samesite: %s\n"
|
||||
+ % (char, e)
|
||||
+ )
|
||||
+
|
||||
class SetCookieOverwriteHandler(RequestHandler):
|
||||
def get(self):
|
||||
self.set_cookie("a", "b", domain="example.com")
|
||||
@@ -329,6 +387,7 @@ class CookieTest(WebTestCase):
|
||||
("/get", GetCookieHandler),
|
||||
("/set_domain", SetCookieDomainHandler),
|
||||
("/special_char", SetCookieSpecialCharHandler),
|
||||
+ ("/forbidden_char", SetCookieForbiddenCharHandler),
|
||||
("/set_overwrite", SetCookieOverwriteHandler),
|
||||
("/set_max_age", SetCookieMaxAgeHandler),
|
||||
("/set_expires_days", SetCookieExpiresDaysHandler),
|
||||
@@ -385,6 +444,12 @@ class CookieTest(WebTestCase):
|
||||
response = self.fetch("/get", headers={"Cookie": header})
|
||||
self.assertEqual(response.body, utf8(expected))
|
||||
|
||||
+ def test_set_cookie_forbidden_char(self):
|
||||
+ response = self.fetch("/forbidden_char")
|
||||
+ self.assertEqual(response.code, 200)
|
||||
+ self.maxDiff = 10000
|
||||
+ self.assertMultiLineEqual(to_unicode(response.body), "")
|
||||
+
|
||||
def test_set_cookie_overwrite(self):
|
||||
response = self.fetch("/set_overwrite")
|
||||
headers = response.headers.get_list("Set-Cookie")
|
||||
diff --git a/tornado/web.py b/tornado/web.py
|
||||
index 8a740504..4b70ea93 100644
|
||||
--- a/tornado/web.py
|
||||
+++ b/tornado/web.py
|
||||
@@ -643,9 +643,30 @@ class RequestHandler(object):
|
||||
# The cookie library only accepts type str, in both python 2 and 3
|
||||
name = escape.native_str(name)
|
||||
value = escape.native_str(value)
|
||||
- if re.search(r"[\x00-\x20]", name + value):
|
||||
- # Don't let us accidentally inject bad stuff
|
||||
- raise ValueError("Invalid cookie %r: %r" % (name, value))
|
||||
+ if re.search(r"[\x00-\x20]", value):
|
||||
+ # Legacy check for control characters in cookie values. This check is no longer needed
|
||||
+ # since the cookie library escapes these characters correctly now. It will be removed
|
||||
+ # in the next feature release.
|
||||
+ raise ValueError(f"Invalid cookie {name!r}: {value!r}")
|
||||
+ for attr_name, attr_value in [
|
||||
+ ("name", name),
|
||||
+ ("domain", domain),
|
||||
+ ("path", path),
|
||||
+ ("samesite", samesite),
|
||||
+ ]:
|
||||
+ # Cookie attributes may not contain control characters or semicolons (except when
|
||||
+ # escaped in the value). A check for control characters was added to the http.cookies
|
||||
+ # library in a Feb 2026 security release; as of March it still does not check for
|
||||
+ # semicolons.
|
||||
+ #
|
||||
+ # When a semicolon check is added to the standard library (and the release has had time
|
||||
+ # for adoption), this check may be removed, but be mindful of the fact that this may
|
||||
+ # change the timing of the exception (to the generation of the Set-Cookie header in
|
||||
+ # flush()). We m
|
||||
+ if attr_value is not None and re.search(r"[\x00-\x20\x3b\x7f]", attr_value):
|
||||
+ raise http.cookies.CookieError(
|
||||
+ f"Invalid cookie attribute {attr_name}={attr_value!r} for cookie {name!r}"
|
||||
+ )
|
||||
if not hasattr(self, "_new_cookie"):
|
||||
self._new_cookie = (
|
||||
http.cookies.SimpleCookie()
|
||||
@@ -11,6 +11,7 @@ SRC_URI[sha256sum] = "92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237
|
||||
SRC_URI += "file://CVE-2025-47287.patch \
|
||||
file://CVE-2025-67724.patch \
|
||||
file://CVE-2025-67726.patch \
|
||||
file://CVE-2026-35536.patch \
|
||||
"
|
||||
|
||||
inherit pypi python_setuptools_build_meta
|
||||
|
||||
Reference in New Issue
Block a user