* [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726
@ 2026-03-16 15:13 Thomas Perale via buildroot
2026-03-16 15:13 ` [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049 Thomas Perale via buildroot
2026-03-27 10:02 ` [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
0 siblings, 2 replies; 4+ messages in thread
From: Thomas Perale via buildroot @ 2026-03-16 15:13 UTC (permalink / raw)
To: buildroot; +Cc: James Hilliard
Fixes the following vulnerabilities:
- CVE-2025-67724:
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.set_status
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.
For more information, see:
- https://www.cve.org/CVERecord?id=CVE-2025-67724
- https://github.com/tornadoweb/tornado/commit/9c163aebeaad9e6e7d28bac1f33580eb00b0e421
- CVE-2025-67725:
Tornado is a Python web framework and asynchronous networking library.
In versions 6.5.2 and below, a single maliciously crafted HTTP request
can block the server's event loop for an extended period, caused by
the HTTPHeaders.add method. The function accumulates values using
string concatenation when the same header name is repeated, causing a
Denial of Service (DoS). Due to Python string immutability, each
concatenation copies the entire string, resulting in O(n²) time
complexity. The severity can vary from high if max_header_size has
been increased from its default, to low if it has its default value of
64KB. This issue is fixed in version 6.5.3.
For more information, see:
- https://www.cve.org/CVERecord?id=CVE-2025-67725
- https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
- CVE-2025-67726:
Tornado is a Python web framework and asynchronous networking library.
Versions 6.5.2 and below use an inefficient algorithm when parsing
parameters for HTTP header values, potentially causing a DoS. The
_parseparam function in httputil.py is used to parse specific HTTP
header values, such as those in multipart/form-data and repeatedly
calls string.count() within a nested loop while processing quoted
semicolons. If an attacker sends a request with a large number of
maliciously crafted parameters in a Content-Disposition header, the
server's CPU usage increases quadratically (O(n²)) during parsing. Due
to Tornado's single event loop architecture, a single malicious
request can cause the entire server to become unresponsive for an
extended period. This issue is fixed in version 6.5.3.
For more information, see:
- https://www.cve.org/CVERecord?id=CVE-2025-67726
- https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
---
...-against-invalid-HTTP-reason-phrases.patch | 83 +++++++++++++++++++
...Fix-quadratic-behavior-in-parseparam.patch | 65 +++++++++++++++
package/python-tornado/python-tornado.mk | 6 ++
3 files changed, 154 insertions(+)
create mode 100644 package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
create mode 100644 package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
diff --git a/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch b/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
new file mode 100644
index 0000000000..ac3c9806a2
--- /dev/null
+++ b/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
@@ -0,0 +1,83 @@
+From 9c163aebeaad9e6e7d28bac1f33580eb00b0e421 Mon Sep 17 00:00:00 2001
+From: Ben Darnell <ben@bendarnell.com>
+Date: Wed, 10 Dec 2025 15:15:25 -0500
+Subject: [PATCH] web: Harden against invalid HTTP reason phrases
+
+We allow applications to set custom reason phrases for the HTTP status
+line (to support custom status codes), but if this were exposed to
+untrusted data it could be exploited in various ways. This commit
+guards against invalid reason phrases in both HTTP headers and in
+error pages.
+
+CVE: CVE-2025-67724
+Upstream: https://github.com/tornadoweb/tornado/commit/9c163aebeaad9e6e7d28bac1f33580eb00b0e421
+Signed-off-by: Thomas Perale <thomas.perale@mind.be>
+---
+ tornado/web.py | 25 +++++++++++++++++++------
+ 1 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/tornado/web.py b/tornado/web.py
+index 2f702d6480..2351afdbe2 100644
+--- a/tornado/web.py
++++ b/tornado/web.py
+@@ -359,8 +359,10 @@ def set_status(self, status_code: int, reason: Optional[str] = None) -> None:
+
+ :arg int status_code: Response status code.
+ :arg str reason: Human-readable reason phrase describing the status
+- code. If ``None``, it will be filled in from
+- `http.client.responses` or "Unknown".
++ code (for example, the "Not Found" in ``HTTP/1.1 404 Not Found``).
++ Normally determined automatically from `http.client.responses`; this
++ argument should only be used if you need to use a non-standard
++ status code.
+
+ .. versionchanged:: 5.0
+
+@@ -369,6 +371,14 @@ def set_status(self, status_code: int, reason: Optional[str] = None) -> None:
+ """
+ self._status_code = status_code
+ if reason is not None:
++ if "<" in reason or not httputil._ABNF.reason_phrase.fullmatch(reason):
++ # Logically this would be better as an exception, but this method
++ # is called on error-handling paths that would need some refactoring
++ # to tolerate internal errors cleanly.
++ #
++ # The check for "<" is a defense-in-depth against XSS attacks (we also
++ # escape the reason when rendering error pages).
++ reason = "Unknown"
+ self._reason = escape.native_str(reason)
+ else:
+ self._reason = httputil.responses.get(status_code, "Unknown")
+@@ -1345,7 +1355,8 @@ def send_error(self, status_code: int = 500, **kwargs: Any) -> None:
+ reason = exception.reason
+ self.set_status(status_code, reason=reason)
+ try:
+- self.write_error(status_code, **kwargs)
++ if status_code != 304:
++ self.write_error(status_code, **kwargs)
+ except Exception:
+ app_log.error("Uncaught exception in write_error", exc_info=True)
+ if not self._finished:
+@@ -1373,7 +1384,7 @@ def write_error(self, status_code: int, **kwargs: Any) -> None:
+ self.finish(
+ "<html><title>%(code)d: %(message)s</title>"
+ "<body>%(code)d: %(message)s</body></html>"
+- % {"code": status_code, "message": self._reason}
++ % {"code": status_code, "message": escape.xhtml_escape(self._reason)}
+ )
+
+ @property
+@@ -2520,9 +2531,11 @@ class HTTPError(Exception):
+ mode). May contain ``%s``-style placeholders, which will be filled
+ in with remaining positional parameters.
+ :arg str reason: Keyword-only argument. The HTTP "reason" phrase
+- to pass in the status line along with ``status_code``. Normally
++ to pass in the status line along with ``status_code`` (for example,
++ the "Not Found" in ``HTTP/1.1 404 Not Found``). Normally
+ determined automatically from ``status_code``, but can be used
+- to use a non-standard numeric code.
++ to use a non-standard numeric code. This is not a general-purpose
++ error message.
+ """
+
+ def __init__(
diff --git a/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch b/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
new file mode 100644
index 0000000000..f1f4d5adbf
--- /dev/null
+++ b/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
@@ -0,0 +1,65 @@
+From 771472cfdaeebc0d89a9cc46e249f8891a6b29cd Mon Sep 17 00:00:00 2001
+From: Ben Darnell <ben@bendarnell.com>
+Date: Wed, 10 Dec 2025 10:55:02 -0500
+Subject: [PATCH] httputil: Fix quadratic behavior in _parseparam
+
+Prior to this change, _parseparam had O(n^2) behavior when parsing
+certain inputs, which could be a DoS vector. This change adapts
+logic from the equivalent function in the python standard library
+in https://github.com/python/cpython/pull/136072/files
+
+CVE: CVE-2025-67725
+CVE: CVE-2025-67726
+Upstream: https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
+Signed-off-by: Thomas Perale <thomas.perale@mind.be>
+---
+ tornado/httputil.py | 29 ++++++++++++++++++++++-------
+ tornado/test/httputil_test.py | 23 +++++++++++++++++++++++
+ 2 files changed, 45 insertions(+), 7 deletions(-)
+
+diff --git a/tornado/httputil.py b/tornado/httputil.py
+index 1c48db414..7fa30975d 100644
+--- a/tornado/httputil.py
++++ b/tornado/httputil.py
+@@ -1094,19 +1094,34 @@ def parse_response_start_line(line: str) -> ResponseStartLine:
+ # It has also been modified to support valueless parameters as seen in
+ # websocket extension negotiations, and to support non-ascii values in
+ # RFC 2231/5987 format.
++#
++# _parseparam has been further modified with the logic from
++# https://github.com/python/cpython/pull/136072/files
++# to avoid quadratic behavior when parsing semicolons in quoted strings.
++#
++# TODO: See if we can switch to email.message.Message for this functionality.
++# This is the suggested replacement for the cgi.py module now that cgi has
++# been removed from recent versions of Python. We need to verify that
++# the email module is consistent with our existing behavior (and all relevant
++# RFCs for multipart/form-data) before making this change.
+
+
+ def _parseparam(s: str) -> Generator[str, None, None]:
+- while s[:1] == ";":
+- s = s[1:]
+- end = s.find(";")
+- while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
+- end = s.find(";", end + 1)
++ start = 0
++ while s.find(";", start) == start:
++ start += 1
++ end = s.find(";", start)
++ ind, diff = start, 0
++ while end > 0:
++ diff += s.count('"', ind, end) - s.count('\\"', ind, end)
++ if diff % 2 == 0:
++ break
++ end, ind = ind, s.find(";", end + 1)
+ if end < 0:
+ end = len(s)
+- f = s[:end]
++ f = s[start:end]
+ yield f.strip()
+- s = s[end:]
++ start = end
+
+
+ def _parse_header(line: str) -> Tuple[str, Dict[str, str]]:
diff --git a/package/python-tornado/python-tornado.mk b/package/python-tornado/python-tornado.mk
index 0a33a57ed4..3e0b79443c 100644
--- a/package/python-tornado/python-tornado.mk
+++ b/package/python-tornado/python-tornado.mk
@@ -16,4 +16,10 @@ PYTHON_TORNADO_SETUP_TYPE = setuptools
# 0001-httputil-raise-errors-instead-of-logging-in.patch
PYTHON_TORNADO_IGNORE_CVES += CVE-2025-47287
+# 0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
+PYTHON_TORNADO_IGNORE_CVES += CVE-2025-67724
+
+# 0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
+PYTHON_TORNADO_IGNORE_CVES += CVE-2025-67725 CVE-2025-67726
+
$(eval $(python-package))
--
2.53.0
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049
2026-03-16 15:13 [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
@ 2026-03-16 15:13 ` Thomas Perale via buildroot
2026-03-27 10:02 ` Thomas Perale via buildroot
2026-03-27 10:02 ` [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
1 sibling, 1 reply; 4+ messages in thread
From: Thomas Perale via buildroot @ 2026-03-16 15:13 UTC (permalink / raw)
To: buildroot; +Cc: James Hilliard
Fixes the following vulnerability:
- CVE-2026-24049:
wheel is a command line tool for manipulating Python wheel files, as
defined in PEP 427. In versions 0.40.0 through 0.46.1, the unpack
function is vulnerable to file permission modification through
mishandling of file permissions after extraction. The logic blindly
trusts the filename from the archive header for the chmod operation,
even though the extraction process itself might have sanitized the
path. Attackers can craft a malicious wheel file that, when unpacked,
changes the permissions of critical system files (e.g., /etc/passwd,
SSH keys, config files), allowing for Privilege Escalation or
arbitrary code execution by modifying now-writable scripts. This issue
has been fixed in version 0.46.2.
For more information, see:
- https://www.cve.org/CVERecord?id=CVE-2026-24049
- https://github.com/advisories/GHSA-8rrh-rw8j-w5fx
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
---
...d-security-issue-around-wheel-unpack.patch | 35 +++++++++++++++++++
package/python-wheel/python-wheel.mk | 3 ++
2 files changed, 38 insertions(+)
create mode 100644 package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
diff --git a/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch b/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
new file mode 100644
index 0000000000..8640dfa291
--- /dev/null
+++ b/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
@@ -0,0 +1,35 @@
+From 7a7d2de96b22a9adf9208afcc9547e1001569fef Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= <alex.gronholm@nextday.fi>
+Date: Thu, 22 Jan 2026 01:41:14 +0200
+Subject: [PATCH] Fixed security issue around wheel unpack (#675)
+
+A maliciously crafted wheel could cause the permissions of a file outside the unpack tree to be altered.
+
+CVE: CVE-2026-24049
+Upstream: https://github.com/pypa/wheel/commit/7a7d2de96b22a9adf9208afcc9547e1001569fef.patch
+[thomas: change filename, remove tests]
+Signed-off-by: Thomas Perale <thomas.perale@mind.be>
+---
+ src/wheel/cli/unpack.py | 4 ++--
+ 3 files changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/src/wheel/cli/unpack.py b/src/wheel/cli/unpack.py
+index d48840e6e..83dc7423f 100644
+--- a/src/wheel/cli/unpack.py
++++ b/src/wheel/cli/unpack.py
+@@ -19,12 +19,12 @@ def unpack(path: str, dest: str = ".") -> None:
+ destination = Path(dest) / namever
+ print(f"Unpacking to: {destination}...", end="", flush=True)
+ for zinfo in wf.filelist:
+- wf.extract(zinfo, destination)
++ target_path = Path(wf.extract(zinfo, destination))
+
+ # Set permissions to the same values as they were set in the archive
+ # We have to do this manually due to
+ # https://github.com/python/cpython/issues/59999
+ permissions = zinfo.external_attr >> 16 & 0o777
+- destination.joinpath(zinfo.filename).chmod(permissions)
++ target_path.chmod(permissions)
+
+ print("OK")
+
diff --git a/package/python-wheel/python-wheel.mk b/package/python-wheel/python-wheel.mk
index 417db7c167..ae02d21feb 100644
--- a/package/python-wheel/python-wheel.mk
+++ b/package/python-wheel/python-wheel.mk
@@ -13,4 +13,7 @@ PYTHON_WHEEL_LICENSE_FILES = LICENSE.txt
PYTHON_WHEEL_CPE_ID_VENDOR = wheel_project
PYTHON_WHEEL_CPE_ID_PRODUCT = wheel
+# 0001-fixed-security-issue-around-wheel-unpack.patch
+PYTHON_WHEEL_IGNORE_CVES += CVE-2026-24049
+
$(eval $(host-python-package))
--
2.53.0
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726
2026-03-16 15:13 [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
2026-03-16 15:13 ` [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049 Thomas Perale via buildroot
@ 2026-03-27 10:02 ` Thomas Perale via buildroot
1 sibling, 0 replies; 4+ messages in thread
From: Thomas Perale via buildroot @ 2026-03-27 10:02 UTC (permalink / raw)
To: Thomas Perale; +Cc: buildroot
In reply of:
> Fixes the following vulnerabilities:
>
> - CVE-2025-67724:
> 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.set_status
> 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.
>
> For more information, see:
> - https://www.cve.org/CVERecord?id=CVE-2025-67724
> - https://github.com/tornadoweb/tornado/commit/9c163aebeaad9e6e7d28bac1f33580eb00b0e421
>
> - CVE-2025-67725:
> Tornado is a Python web framework and asynchronous networking library.
> In versions 6.5.2 and below, a single maliciously crafted HTTP request
> can block the server's event loop for an extended period, caused by
> the HTTPHeaders.add method. The function accumulates values using
> string concatenation when the same header name is repeated, causing a
> Denial of Service (DoS). Due to Python string immutability, each
> concatenation copies the entire string, resulting in O(n²) time
> complexity. The severity can vary from high if max_header_size has
> been increased from its default, to low if it has its default value of
> 64KB. This issue is fixed in version 6.5.3.
>
> For more information, see:
> - https://www.cve.org/CVERecord?id=CVE-2025-67725
> - https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
>
> - CVE-2025-67726:
> Tornado is a Python web framework and asynchronous networking library.
> Versions 6.5.2 and below use an inefficient algorithm when parsing
> parameters for HTTP header values, potentially causing a DoS. The
> _parseparam function in httputil.py is used to parse specific HTTP
> header values, such as those in multipart/form-data and repeatedly
> calls string.count() within a nested loop while processing quoted
> semicolons. If an attacker sends a request with a large number of
> maliciously crafted parameters in a Content-Disposition header, the
> server's CPU usage increases quadratically (O(n²)) during parsing. Due
> to Tornado's single event loop architecture, a single malicious
> request can cause the entire server to become unresponsive for an
> extended period. This issue is fixed in version 6.5.3.
>
> For more information, see:
> - https://www.cve.org/CVERecord?id=CVE-2025-67726
> - https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
>
> Signed-off-by: Thomas Perale <thomas.perale@mind.be>
Applied to 2025.02.x. Thanks
> ---
> ...-against-invalid-HTTP-reason-phrases.patch | 83 +++++++++++++++++++
> ...Fix-quadratic-behavior-in-parseparam.patch | 65 +++++++++++++++
> package/python-tornado/python-tornado.mk | 6 ++
> 3 files changed, 154 insertions(+)
> create mode 100644 package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
> create mode 100644 package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
>
> diff --git a/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch b/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
> new file mode 100644
> index 0000000000..ac3c9806a2
> --- /dev/null
> +++ b/package/python-tornado/0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
> @@ -0,0 +1,83 @@
> +From 9c163aebeaad9e6e7d28bac1f33580eb00b0e421 Mon Sep 17 00:00:00 2001
> +From: Ben Darnell <ben@bendarnell.com>
> +Date: Wed, 10 Dec 2025 15:15:25 -0500
> +Subject: [PATCH] web: Harden against invalid HTTP reason phrases
> +
> +We allow applications to set custom reason phrases for the HTTP status
> +line (to support custom status codes), but if this were exposed to
> +untrusted data it could be exploited in various ways. This commit
> +guards against invalid reason phrases in both HTTP headers and in
> +error pages.
> +
> +CVE: CVE-2025-67724
> +Upstream: https://github.com/tornadoweb/tornado/commit/9c163aebeaad9e6e7d28bac1f33580eb00b0e421
> +Signed-off-by: Thomas Perale <thomas.perale@mind.be>
> +---
> + tornado/web.py | 25 +++++++++++++++++++------
> + 1 files changed, 19 insertions(+), 6 deletions(-)
> +
> +diff --git a/tornado/web.py b/tornado/web.py
> +index 2f702d6480..2351afdbe2 100644
> +--- a/tornado/web.py
> ++++ b/tornado/web.py
> +@@ -359,8 +359,10 @@ def set_status(self, status_code: int, reason: Optional[str] = None) -> None:
> +
> + :arg int status_code: Response status code.
> + :arg str reason: Human-readable reason phrase describing the status
> +- code. If ``None``, it will be filled in from
> +- `http.client.responses` or "Unknown".
> ++ code (for example, the "Not Found" in ``HTTP/1.1 404 Not Found``).
> ++ Normally determined automatically from `http.client.responses`; this
> ++ argument should only be used if you need to use a non-standard
> ++ status code.
> +
> + .. versionchanged:: 5.0
> +
> +@@ -369,6 +371,14 @@ def set_status(self, status_code: int, reason: Optional[str] = None) -> None:
> + """
> + self._status_code = status_code
> + if reason is not None:
> ++ if "<" in reason or not httputil._ABNF.reason_phrase.fullmatch(reason):
> ++ # Logically this would be better as an exception, but this method
> ++ # is called on error-handling paths that would need some refactoring
> ++ # to tolerate internal errors cleanly.
> ++ #
> ++ # The check for "<" is a defense-in-depth against XSS attacks (we also
> ++ # escape the reason when rendering error pages).
> ++ reason = "Unknown"
> + self._reason = escape.native_str(reason)
> + else:
> + self._reason = httputil.responses.get(status_code, "Unknown")
> +@@ -1345,7 +1355,8 @@ def send_error(self, status_code: int = 500, **kwargs: Any) -> None:
> + reason = exception.reason
> + self.set_status(status_code, reason=reason)
> + try:
> +- self.write_error(status_code, **kwargs)
> ++ if status_code != 304:
> ++ self.write_error(status_code, **kwargs)
> + except Exception:
> + app_log.error("Uncaught exception in write_error", exc_info=True)
> + if not self._finished:
> +@@ -1373,7 +1384,7 @@ def write_error(self, status_code: int, **kwargs: Any) -> None:
> + self.finish(
> + "<html><title>%(code)d: %(message)s</title>"
> + "<body>%(code)d: %(message)s</body></html>"
> +- % {"code": status_code, "message": self._reason}
> ++ % {"code": status_code, "message": escape.xhtml_escape(self._reason)}
> + )
> +
> + @property
> +@@ -2520,9 +2531,11 @@ class HTTPError(Exception):
> + mode). May contain ``%s``-style placeholders, which will be filled
> + in with remaining positional parameters.
> + :arg str reason: Keyword-only argument. The HTTP "reason" phrase
> +- to pass in the status line along with ``status_code``. Normally
> ++ to pass in the status line along with ``status_code`` (for example,
> ++ the "Not Found" in ``HTTP/1.1 404 Not Found``). Normally
> + determined automatically from ``status_code``, but can be used
> +- to use a non-standard numeric code.
> ++ to use a non-standard numeric code. This is not a general-purpose
> ++ error message.
> + """
> +
> + def __init__(
> diff --git a/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch b/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
> new file mode 100644
> index 0000000000..f1f4d5adbf
> --- /dev/null
> +++ b/package/python-tornado/0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
> @@ -0,0 +1,65 @@
> +From 771472cfdaeebc0d89a9cc46e249f8891a6b29cd Mon Sep 17 00:00:00 2001
> +From: Ben Darnell <ben@bendarnell.com>
> +Date: Wed, 10 Dec 2025 10:55:02 -0500
> +Subject: [PATCH] httputil: Fix quadratic behavior in _parseparam
> +
> +Prior to this change, _parseparam had O(n^2) behavior when parsing
> +certain inputs, which could be a DoS vector. This change adapts
> +logic from the equivalent function in the python standard library
> +in https://github.com/python/cpython/pull/136072/files
> +
> +CVE: CVE-2025-67725
> +CVE: CVE-2025-67726
> +Upstream: https://github.com/tornadoweb/tornado/commit/771472cfdaeebc0d89a9cc46e249f8891a6b29cd
> +Signed-off-by: Thomas Perale <thomas.perale@mind.be>
> +---
> + tornado/httputil.py | 29 ++++++++++++++++++++++-------
> + tornado/test/httputil_test.py | 23 +++++++++++++++++++++++
> + 2 files changed, 45 insertions(+), 7 deletions(-)
> +
> +diff --git a/tornado/httputil.py b/tornado/httputil.py
> +index 1c48db414..7fa30975d 100644
> +--- a/tornado/httputil.py
> ++++ b/tornado/httputil.py
> +@@ -1094,19 +1094,34 @@ def parse_response_start_line(line: str) -> ResponseStartLine:
> + # It has also been modified to support valueless parameters as seen in
> + # websocket extension negotiations, and to support non-ascii values in
> + # RFC 2231/5987 format.
> ++#
> ++# _parseparam has been further modified with the logic from
> ++# https://github.com/python/cpython/pull/136072/files
> ++# to avoid quadratic behavior when parsing semicolons in quoted strings.
> ++#
> ++# TODO: See if we can switch to email.message.Message for this functionality.
> ++# This is the suggested replacement for the cgi.py module now that cgi has
> ++# been removed from recent versions of Python. We need to verify that
> ++# the email module is consistent with our existing behavior (and all relevant
> ++# RFCs for multipart/form-data) before making this change.
> +
> +
> + def _parseparam(s: str) -> Generator[str, None, None]:
> +- while s[:1] == ";":
> +- s = s[1:]
> +- end = s.find(";")
> +- while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
> +- end = s.find(";", end + 1)
> ++ start = 0
> ++ while s.find(";", start) == start:
> ++ start += 1
> ++ end = s.find(";", start)
> ++ ind, diff = start, 0
> ++ while end > 0:
> ++ diff += s.count('"', ind, end) - s.count('\\"', ind, end)
> ++ if diff % 2 == 0:
> ++ break
> ++ end, ind = ind, s.find(";", end + 1)
> + if end < 0:
> + end = len(s)
> +- f = s[:end]
> ++ f = s[start:end]
> + yield f.strip()
> +- s = s[end:]
> ++ start = end
> +
> +
> + def _parse_header(line: str) -> Tuple[str, Dict[str, str]]:
> diff --git a/package/python-tornado/python-tornado.mk b/package/python-tornado/python-tornado.mk
> index 0a33a57ed4..3e0b79443c 100644
> --- a/package/python-tornado/python-tornado.mk
> +++ b/package/python-tornado/python-tornado.mk
> @@ -16,4 +16,10 @@ PYTHON_TORNADO_SETUP_TYPE = setuptools
> # 0001-httputil-raise-errors-instead-of-logging-in.patch
> PYTHON_TORNADO_IGNORE_CVES += CVE-2025-47287
>
> +# 0002-web-Harden-against-invalid-HTTP-reason-phrases.patch
> +PYTHON_TORNADO_IGNORE_CVES += CVE-2025-67724
> +
> +# 0003-httputil-Fix-quadratic-behavior-in-parseparam.patch
> +PYTHON_TORNADO_IGNORE_CVES += CVE-2025-67725 CVE-2025-67726
> +
> $(eval $(python-package))
> --
> 2.53.0
>
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049
2026-03-16 15:13 ` [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049 Thomas Perale via buildroot
@ 2026-03-27 10:02 ` Thomas Perale via buildroot
0 siblings, 0 replies; 4+ messages in thread
From: Thomas Perale via buildroot @ 2026-03-27 10:02 UTC (permalink / raw)
To: Thomas Perale; +Cc: buildroot
In reply of:
> Fixes the following vulnerability:
>
> - CVE-2026-24049:
> wheel is a command line tool for manipulating Python wheel files, as
> defined in PEP 427. In versions 0.40.0 through 0.46.1, the unpack
> function is vulnerable to file permission modification through
> mishandling of file permissions after extraction. The logic blindly
> trusts the filename from the archive header for the chmod operation,
> even though the extraction process itself might have sanitized the
> path. Attackers can craft a malicious wheel file that, when unpacked,
> changes the permissions of critical system files (e.g., /etc/passwd,
> SSH keys, config files), allowing for Privilege Escalation or
> arbitrary code execution by modifying now-writable scripts. This issue
> has been fixed in version 0.46.2.
>
> For more information, see:
> - https://www.cve.org/CVERecord?id=CVE-2026-24049
> - https://github.com/advisories/GHSA-8rrh-rw8j-w5fx
>
> Signed-off-by: Thomas Perale <thomas.perale@mind.be>
Applied to 2025.02.x. Thanks
> ---
> ...d-security-issue-around-wheel-unpack.patch | 35 +++++++++++++++++++
> package/python-wheel/python-wheel.mk | 3 ++
> 2 files changed, 38 insertions(+)
> create mode 100644 package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
>
> diff --git a/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch b/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
> new file mode 100644
> index 0000000000..8640dfa291
> --- /dev/null
> +++ b/package/python-wheel/0001-fixed-security-issue-around-wheel-unpack.patch
> @@ -0,0 +1,35 @@
> +From 7a7d2de96b22a9adf9208afcc9547e1001569fef Mon Sep 17 00:00:00 2001
> +From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= <alex.gronholm@nextday.fi>
> +Date: Thu, 22 Jan 2026 01:41:14 +0200
> +Subject: [PATCH] Fixed security issue around wheel unpack (#675)
> +
> +A maliciously crafted wheel could cause the permissions of a file outside the unpack tree to be altered.
> +
> +CVE: CVE-2026-24049
> +Upstream: https://github.com/pypa/wheel/commit/7a7d2de96b22a9adf9208afcc9547e1001569fef.patch
> +[thomas: change filename, remove tests]
> +Signed-off-by: Thomas Perale <thomas.perale@mind.be>
> +---
> + src/wheel/cli/unpack.py | 4 ++--
> + 3 files changed, 27 insertions(+), 2 deletions(-)
> +
> +diff --git a/src/wheel/cli/unpack.py b/src/wheel/cli/unpack.py
> +index d48840e6e..83dc7423f 100644
> +--- a/src/wheel/cli/unpack.py
> ++++ b/src/wheel/cli/unpack.py
> +@@ -19,12 +19,12 @@ def unpack(path: str, dest: str = ".") -> None:
> + destination = Path(dest) / namever
> + print(f"Unpacking to: {destination}...", end="", flush=True)
> + for zinfo in wf.filelist:
> +- wf.extract(zinfo, destination)
> ++ target_path = Path(wf.extract(zinfo, destination))
> +
> + # Set permissions to the same values as they were set in the archive
> + # We have to do this manually due to
> + # https://github.com/python/cpython/issues/59999
> + permissions = zinfo.external_attr >> 16 & 0o777
> +- destination.joinpath(zinfo.filename).chmod(permissions)
> ++ target_path.chmod(permissions)
> +
> + print("OK")
> +
> diff --git a/package/python-wheel/python-wheel.mk b/package/python-wheel/python-wheel.mk
> index 417db7c167..ae02d21feb 100644
> --- a/package/python-wheel/python-wheel.mk
> +++ b/package/python-wheel/python-wheel.mk
> @@ -13,4 +13,7 @@ PYTHON_WHEEL_LICENSE_FILES = LICENSE.txt
> PYTHON_WHEEL_CPE_ID_VENDOR = wheel_project
> PYTHON_WHEEL_CPE_ID_PRODUCT = wheel
>
> +# 0001-fixed-security-issue-around-wheel-unpack.patch
> +PYTHON_WHEEL_IGNORE_CVES += CVE-2026-24049
> +
> $(eval $(host-python-package))
> --
> 2.53.0
>
> _______________________________________________
> buildroot mailing list
> buildroot@buildroot.org
> https://lists.buildroot.org/mailman/listinfo/buildroot
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-27 10:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-16 15:13 [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
2026-03-16 15:13 ` [Buildroot] [2025.02.x, PATCH 2/2] package/python-wheel: patch CVE-2026-24049 Thomas Perale via buildroot
2026-03-27 10:02 ` Thomas Perale via buildroot
2026-03-27 10:02 ` [Buildroot] [2025.02.x, PATCH 1/2] package/python-tornado: patch CVE-2025-67724, CVE-2025-67725, CVE-2025-67726 Thomas Perale via buildroot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox