From patchwork Wed Feb 4 16:29:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8441CE9D40C for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24634.1770222568447206671 for ; Wed, 04 Feb 2026 08:29:28 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=P6toe3Uc; spf=pass (domain: gmail.com, ip: 209.85.221.47, mailfrom: skandigraun@gmail.com) Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-42fb0fc5aa9so36510f8f.1 for ; Wed, 04 Feb 2026 08:29:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222566; x=1770827366; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=Hh9s1hs0niS/SVsBhPWTtzxLQIoQFquPjdCrE8lK4sA=; b=P6toe3Uca4XG5vlGBloU6Ab6phlh5/PDJxP/ItD8VSZu/+ZQDFZStHmoCt2CizsNKB czuJrsjNBYJBGwldWUupeCL9CRuvjIkhIIjClGc0I8xwXaQZDZKIsmtOlSAxkddoIizF GKp6LLYRsfItZjkcitJt+XZqWySqFRF+8+rU1R0Iu6IS+l3BI9USCijgEEbizrCdfNQn +sgwPpUEpC/+2C1KgnQIg0pXL2YOMHqJyWEeDYgASIA0lr/YznWlQ4UvYDwHYO2m2KFe gumoB6EnWon0Kd+imLWc+l7bNmv2t99mgPn6EIG6dk4ZQhjWLrnA3K0ZDMGMLVVYIkZO 4Qkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222566; x=1770827366; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Hh9s1hs0niS/SVsBhPWTtzxLQIoQFquPjdCrE8lK4sA=; b=OyCDOa2JvqSZ5Jd3TuzklKqugwcgasnWXg3ooS9SYdjYfYvS7uKdaRV56Jv2B4D5l0 EJtSsNlzHFmw7fXCUWRc/kS+6SZb8dv+CVt6soOxxvVuXFTURVKyw4ATyG1m+R7iGUPV 91nkcridIt/I6gP6Q5B+fgHR2GwfWQqVqX0adCLrlSc0w8ETgSS0Yjb2q4C+12Wjx84N 1KKSc+74fp0p90SX0zHPg2SPY/D18a1VvxiiozdV4/TmmThLSXSPAPEfDDIOI+TB3nAE hn1T6lkq1gmHnaEHV5yjakU327Mlvuj1lJpLuFF5JicuMNbBEyV+ok6siI6za1JPjjjh U1cg== X-Gm-Message-State: AOJu0Yy/bFEZf56j2EbD1BEJ22iM5I/JtQ3CSKA+WDrZa/NzAO1V+Dxp 54xKl7Syvekws/J02/HjMON59W+gfdXslCQRR2mfPFOEr2wrHcW7Ag3W9JZc6g== X-Gm-Gg: AZuq6aI96p2qnxY/swybU2kZrTMjEr8rFfU3oVcA7dvvNvRRXONSVxScIYmdwfgn2VF tZ/mCpyyrf/ImDwXbHcuxMwv86IvBqTp5Rlc4z6KKETnWCtFWmviH4upW6efvE2hhhB6mtxSEQ2 xT5y6ihdtqu/5rHu70y0A2dnJunPmjLurmqMvVWoQwZxNuM7dtGJ6ZW+v4ZlYpO4vQ6+MyhvbnM P/C27P9+Jqu90NVgbFfsh0V+1PXCpVBYvoP52IBepYMEi/2TM/qHs2Q3VaRk9FMZfulOOyByUdh E5wPpEQGCoS9RDoGBRcctEwWa/YvQAWDVezsOk/Z9PypCuG769d3A+UegmvExGVpkiLS3gTcIlb vri6u/zi7Ji4ZLr1pwxobCanb/tt37JInnCLDHpd9uIXuHQAcBV1vzMhQjhf0E2iJph8lgKhJXT Ney7dUdgo9 X-Received: by 2002:a05:600c:3acd:b0:46e:4a13:e6c6 with SMTP id 5b1f17b1804b1-4830e987c5cmr50309985e9.19.1770222565863; Wed, 04 Feb 2026 08:29:25 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:25 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 1/7] python3-aiohttp: patch CVE-2025-69224 Date: Wed, 4 Feb 2026 17:29:16 +0100 Message-ID: <20260204162924.3042284-1-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124136 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69224 Backport the patch indicated by the NVD advisory. Only a part of the tests were backported, because some of the new tests require a compression method that is not supported yet by this version. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69224.patch | 93 +++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 1 + 2 files changed, 94 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69224.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69224.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69224.patch new file mode 100644 index 0000000000..7f36e699fd --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69224.patch @@ -0,0 +1,93 @@ +From 225412b13f66a76a7222d7719777e6162638faa3 Mon Sep 17 00:00:00 2001 +From: Sam Bull +Date: Sat, 3 Jan 2026 00:02:45 +0000 +Subject: [PATCH] Reject non-ascii characters in some headers (#11886) (#11902) + +(cherry picked from commit 5affd64f86d28a16a8f8e6fea2d217c99bf7831f) + +CVE: CVE-2025-69224 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/32677f2adfd907420c078dda6b79225c6f4ebce0] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/_http_parser.pyx | 6 +++--- + aiohttp/http_parser.py | 8 ++++++-- + tests/test_http_parser.py | 16 +++++++++++++++- + 3 files changed, 24 insertions(+), 6 deletions(-) + +diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx +index 16893f0..23f1dd1 100644 +--- a/aiohttp/_http_parser.pyx ++++ b/aiohttp/_http_parser.pyx +@@ -421,7 +421,8 @@ cdef class HttpParser: + headers = CIMultiDictProxy(CIMultiDict(self._headers)) + + if self._cparser.type == cparser.HTTP_REQUEST: +- allowed = upgrade and headers.get("upgrade", "").lower() in ALLOWED_UPGRADES ++ h_upg = headers.get("upgrade", "") ++ allowed = upgrade and h_upg.isascii() and h_upg.lower() in ALLOWED_UPGRADES + if allowed or self._cparser.method == cparser.HTTP_CONNECT: + self._upgraded = True + else: +@@ -436,8 +437,7 @@ cdef class HttpParser: + enc = self._content_encoding + if enc is not None: + self._content_encoding = None +- enc = enc.lower() +- if enc in ('gzip', 'deflate', 'br'): ++ if enc.isascii() and enc.lower() in {"gzip", "deflate", "br"}: + encoding = enc + + if self._cparser.type == cparser.HTTP_REQUEST: +diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py +index 9f864b2..bc8f7da 100644 +--- a/aiohttp/http_parser.py ++++ b/aiohttp/http_parser.py +@@ -232,7 +232,9 @@ class HeadersParser: + + def _is_supported_upgrade(headers: CIMultiDictProxy[str]) -> bool: + """Check if the upgrade header is supported.""" +- return headers.get(hdrs.UPGRADE, "").lower() in {"tcp", "websocket"} ++ u = headers.get(hdrs.UPGRADE, "") ++ # .lower() can transform non-ascii characters. ++ return u.isascii() and u.lower() in {"tcp", "websocket"} + + + class HttpParser(abc.ABC, Generic[_MsgT]): +@@ -664,7 +666,9 @@ class HttpRequestParser(HttpParser[RawRequestMessage]): + ) + + def _is_chunked_te(self, te: str) -> bool: +- if te.rsplit(",", maxsplit=1)[-1].strip(" \t").lower() == "chunked": ++ te = te.rsplit(",", maxsplit=1)[-1].strip(" \t") ++ # .lower() transforms some non-ascii chars, so must check first. ++ if te.isascii() and te.lower() == "chunked": + return True + # https://www.rfc-editor.org/rfc/rfc9112#section-6.3-2.4.3 + raise BadHttpMessage("Request has invalid `Transfer-Encoding`") +diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py +index 385452c..d4c1768 100644 +--- a/tests/test_http_parser.py ++++ b/tests/test_http_parser.py +@@ -468,7 +468,21 @@ def test_request_chunked(parser) -> None: + assert isinstance(payload, streams.StreamReader) + + +-def test_request_te_chunked_with_content_length(parser: Any) -> None: ++def test_te_header_non_ascii(parser: HttpRequestParser) -> None: ++ # K = Kelvin sign, not valid ascii. ++ text = "GET /test HTTP/1.1\r\nTransfer-Encoding: chunKed\r\n\r\n" ++ with pytest.raises(http_exceptions.BadHttpMessage): ++ parser.feed_data(text.encode()) ++ ++ ++def test_upgrade_header_non_ascii(parser: HttpRequestParser) -> None: ++ # K = Kelvin sign, not valid ascii. ++ text = "GET /test HTTP/1.1\r\nUpgrade: websocKet\r\n\r\n" ++ messages, upgrade, tail = parser.feed_data(text.encode()) ++ assert not upgrade ++ ++ ++def test_request_te_chunked_with_content_length(parser: HttpRequestParser) -> None: + text = ( + b"GET /test HTTP/1.1\r\n" + b"content-length: 1234\r\n" diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index b6344d4c68..4341e128a5 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -4,6 +4,7 @@ HOMEPAGE = "https://github.com/aio-libs/aiohttp" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=748073912af33aa59430d3702aa32d41" +SRC_URI += "file://CVE-2025-69224.patch" SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" inherit python_setuptools_build_meta pypi From patchwork Wed Feb 4 16:29:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80440 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A306AE9D40F for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24635.1770222568580983750 for ; Wed, 04 Feb 2026 08:29:28 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=P+raeoPa; spf=pass (domain: gmail.com, ip: 209.85.128.44, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-4801eb2c0a5so66449715e9.3 for ; Wed, 04 Feb 2026 08:29:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222567; x=1770827367; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=7r3Ze8S3SadA4IJrQNtDbJYaAqnxV1n+YAV1JDwgpB4=; b=P+raeoPaIdsR4drN0oRK71kXRx6h+3Pa8FtbOWtlzyrDw3WDLcFi/jYJMOn94ywrwj m8UNIL4wFHNAPNwAW7VNwvVyHIhmjb8Z8NOzeEiqJcecJxXxyP0mUMIRToD1xsmdvV2m qVISSPALfoBEnXjXEO0x7DEMZfh/EqyPQUBZhNpMW6JDdKoFKCPzKnJEkBqffmqJ4Y5i ZV5x1sn2XcJLY72uu8U2l79Dm8mJkTJh+tB+fG+mqD/T9RbDIMiudUL483Eu/Z5KXRWv PP/6Z2mcHR15N1/xeGPDJlEOMuEOVmbPJ+tTf/UWWdG7LbJnhS1/cmSacDrfdJ2CWGiu 43QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222567; x=1770827367; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=7r3Ze8S3SadA4IJrQNtDbJYaAqnxV1n+YAV1JDwgpB4=; b=gFhSMZMI+JI8heM64XWsdHEPRC+xkdLRN/jdmNCV4ABPCjQ5v0dh/R8b3u9UMXei++ J9VB+LDRrGp1yW3DfwQCK5kcvjDel29jvxdrb70WIEmNYVhBCbX5X5tt/hW4sGngasB9 rA8KnLTeG7i+/14RHRPpl7f6t+IZ6AIyQhDfl0VT5pzQD/t1oQbt0sZaJjdid5wqkoSs BE+izYHBifRfROzHDC3txeNSxmAMhYDf1ecthteIVem6KrZMUH8GGKATNMexKdqG7tSs XJqqFX3k7BNfv8sLcscaF21UCaPNspTvNgrQDJOe5UVoZkWrI1OD/1k2e0KShuLV6dch 1w3Q== X-Gm-Message-State: AOJu0YzrQeNW/444giM38zGl2Six7WSzVvojvVfqanNqiFWu0ILLLC9U 0dJmw2jtWU/0S9FL1nhmdqN9TlFVSUIEBTWp+XhM2WQZHvnmksnblerSJvADPg== X-Gm-Gg: AZuq6aK+Cw8TYfa7j+iMMg4UpFvZuwsBSgqQRhyQZvXR4N8DTynmHT12x/1zceuM68S rf15Y2yuaOKqP+ApkDcWRBG5UaVfMwFxAy218YnIgzz+8mQ+1DqCyF9vSGbk1h+K7PzlkGVMlNi 6hcOT7vcTKpKWelY6LUZHnrmvmlQW5iDpESLkx8ckfXWdmSsBfbb2mcoofVolWo6hV4vWjCijcU vxk44rBU7dKxgBjJ6s4xChioUCQoUHBwwBClujFhF0wl6+JW0R1RMaJuA68zOrUgheFoYKSjEln 3XBTdhktk9hmfaukS6dyOtpcnlqjHzRGoSHvU7YDqtm1J6semKyKlaV9ArTcbhBK0jfvBre/r2A c+Cl4Z92mMH9Zy8cLi4ZY0iKmzC1MaewSzjtfyO/XCzSUBP4AyF56pajM62Ea0mei+hpn+FAaKk PlHEc4jKcakYGKpQOxeXs= X-Received: by 2002:a05:600c:19cd:b0:477:93f7:bbc5 with SMTP id 5b1f17b1804b1-4830e9402f8mr49885075e9.10.1770222566749; Wed, 04 Feb 2026 08:29:26 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:26 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 2/7] python3-aiohttp: patch CVE-2025-69225 Date: Wed, 4 Feb 2026 17:29:17 +0100 Message-ID: <20260204162924.3042284-2-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124137 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69225 Backport the patch that is referenced by the NVD report. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69225.patch | 49 +++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 4 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69225.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69225.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69225.patch new file mode 100644 index 0000000000..77b39d22dc --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69225.patch @@ -0,0 +1,49 @@ +From a4be27fe28e6cd833fa3045cca10404472d6878d Mon Sep 17 00:00:00 2001 +From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> +Date: Sat, 3 Jan 2026 00:39:41 +0000 +Subject: [PATCH] Reject non-ascii digits in Range header (#11903) + +**This is a backport of PR #11887 as merged into master +(7a067d1905e1eeb921a50010dd0004990dbb3bf0).** + +Co-authored-by: Sam Bull + +CVE: CVE-2025-69225 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/c7b7a044f88c71cefda95ec75cdcfaa4792b3b96] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/web_request.py | 2 +- + tests/test_web_request.py | 7 +++++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py +index 0bc69b7..6e09027 100644 +--- a/aiohttp/web_request.py ++++ b/aiohttp/web_request.py +@@ -607,7 +607,7 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin): + if rng is not None: + try: + pattern = r"^bytes=(\d*)-(\d*)$" +- start, end = re.findall(pattern, rng)[0] ++ start, end = re.findall(pattern, rng, re.ASCII)[0] + except IndexError: # pattern was not found in header + raise ValueError("range not in acceptable format") + +diff --git a/tests/test_web_request.py b/tests/test_web_request.py +index e706e18..da80ca9 100644 +--- a/tests/test_web_request.py ++++ b/tests/test_web_request.py +@@ -243,6 +243,13 @@ def test_range_to_slice_tail_stop() -> None: + assert req.content[req.http_range] == payload[-500:] + + ++def test_range_non_ascii() -> None: ++ # ५ = DEVANAGARI DIGIT FIVE ++ req = make_mocked_request("GET", "/", headers=CIMultiDict([("RANGE", "bytes=4-५")])) ++ with pytest.raises(ValueError, match="range not in acceptable format"): ++ req.http_range ++ ++ + def test_non_keepalive_on_http10() -> None: + req = make_mocked_request("GET", "/", version=HttpVersion(1, 0)) + assert not req.keep_alive diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 4341e128a5..9a45eecb8c 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -4,7 +4,9 @@ HOMEPAGE = "https://github.com/aio-libs/aiohttp" LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=748073912af33aa59430d3702aa32d41" -SRC_URI += "file://CVE-2025-69224.patch" +SRC_URI += "file://CVE-2025-69224.patch \ + file://CVE-2025-69225.patch \ +" SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" inherit python_setuptools_build_meta pypi From patchwork Wed Feb 4 16:29:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC403E9D411 for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24636.1770222569358554011 for ; Wed, 04 Feb 2026 08:29:29 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=Dzg5IYQE; spf=pass (domain: gmail.com, ip: 209.85.128.50, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-480706554beso77795535e9.1 for ; Wed, 04 Feb 2026 08:29:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222568; x=1770827368; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=lzNinIXll6P7zJKV28ARs4GmYP2TUvaQrAF5IGAlf4U=; b=Dzg5IYQEPXjAlevjl/go6EE1Vmz4ZxxUA3wyhVjGiVQYDalswOBbNjpMU12qRmIKoW iVlCGsJ1lBO38DeVXs4vHXQKFxh6ce7rarkX2L9yCkV9R7O3nAy/ljmdcZoY4zhXRZxY ZLB/z4MM649iuXdKXV4cwfPnTJnf8ltXWuIszQplkTWrdSWBdHYA27xwdPZkKnWzaDiu cvnWP5o8+2OEAIxIal7vl2zbFIZ7nxxAY8WiilUQiODNsgUSicT+OHrxMqPbFQnfTSHR e3QmSq61nFSqc4oJxhmOVb2xU5iTEwde54fENM9ag9Ekt7XYG+j/ysvZOPT/DGcfTjB+ nb9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222568; x=1770827368; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=lzNinIXll6P7zJKV28ARs4GmYP2TUvaQrAF5IGAlf4U=; b=UJpFbsFKHYHXrXhfV0ibjB1xfIYgZgvStWTI543IdUcUJDFbQr8H0E+S4SPI5u77D2 /aVTdR0/Cwigle8MTJ8wBGavIdh/9M7e0xYLsLUoxGZhf2YJoXYNAqCzqdEUxFIEF3RA bGHSKu+W66Y/acim87VQh3HR/Z8NG4opc5OElYkCMVOC1ZOptFeGM7u2JFagQrwW43nf m3NAI2LbfABtvqDIl2/MLnP7qjcJQ86hza81QvBjBKzs+nWgkx9LKKEcOC8ANi+BjJEj lmB55p49NJmonWaVt0+dGRcMXqp3W7EpQmm/dWWJXdcwrQZM5hfD9OhPVabjaptyJauz 8Bkw== X-Gm-Message-State: AOJu0YzDk6tSMeXTMhxW+IrgM3NloUybc4IerKoNr6TQYrI0glwCMRp+ rnXXcyuGHQlAgpZV0KL1S0Zizbi4Sljbi25Sa3vy58ehWd4LSpK/66E0jeWyWg== X-Gm-Gg: AZuq6aJM/sMbFdjjv8JSVJ2XVvcb5McAejazyL1uEcqOCp200vdgRnKkxgdVLe9o21b GmvlxWRlwsRrpI/ydKeAmaH6fEY6Et41Gn/RQLur4uyoNFmw72nRllEDLoHiPI30SiC1XBPkavY iM3Xy6Y++N95KJBLB01PnCpaueDN9uJntOU4XfDSIOca1QOJ2gMTxQTSHUo96+U1cRQyEbNPZqS /e+A2stgFS6JkkBtpUtwRtyfF4DQcmE0n/P3+GEbmmxqLoQzfPBbsmDGP3UT9sgQILrH5WBk1Ok 7EFtIv7Aq05a2upRgmjOa6ErJLSGAZapw3peGP/t+FVEOspj/6U4uaepMVTVch7P5e9kkaYFXFS CvYq1sJw4s1UufTUOgpKX+ph/oQy9QsNa7SXGogY6/WoQIsYAzw/9QTTQFI/D3i05pCY3Ryqo8r Na+j/xkGr+ X-Received: by 2002:a05:600c:34c3:b0:480:1a3a:5ce6 with SMTP id 5b1f17b1804b1-4830e93ddd9mr48216775e9.14.1770222567576; Wed, 04 Feb 2026 08:29:27 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:27 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 3/7] python3-aiohttp: patch CVE-2025-69226 Date: Wed, 4 Feb 2026 17:29:18 +0100 Message-ID: <20260204162924.3042284-3-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124138 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69226 Backport the patch that is referenced by the NVD advisory. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69226.patch | 134 ++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 1 + 2 files changed, 135 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69226.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69226.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69226.patch new file mode 100644 index 0000000000..6786546f25 --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69226.patch @@ -0,0 +1,134 @@ +From b330573c65db35ee1228615ec257619b49b918c7 Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 01:55:05 +0000 +Subject: [PATCH] Reject static URLs that traverse outside static root (#11888) + (#11906) + +From: Sam Bull + +(cherry picked from commit 63961fa77fa2443109f25c3d8ab94772d3878626) + +Co-authored-by: J. Nick Koston + +CVE: CVE-2025-69226 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/f2a86fd5ac0383000d1715afddfa704413f0711e] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/web_urldispatcher.py | 18 +++++++++--------- + tests/test_urldispatch.py | 18 +++++++++++++++++- + tests/test_web_sendfile_functional.py | 2 +- + tests/test_web_urldispatcher.py | 4 ++-- + 4 files changed, 29 insertions(+), 13 deletions(-) + +diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py +index 28ae251..a121656 100644 +--- a/aiohttp/web_urldispatcher.py ++++ b/aiohttp/web_urldispatcher.py +@@ -7,6 +7,7 @@ import html + import inspect + import keyword + import os ++import platform + import re + import sys + import warnings +@@ -94,6 +95,7 @@ ROUTE_RE: Final[Pattern[str]] = re.compile( + ) + PATH_SEP: Final[str] = re.escape("/") + ++IS_WINDOWS: Final[bool] = platform.system() == "Windows" + + _ExpectHandler = Callable[[Request], Awaitable[Optional[StreamResponse]]] + _Resolve = Tuple[Optional["UrlMappingMatchInfo"], Set[str]] +@@ -649,7 +651,12 @@ class StaticResource(PrefixResource): + async def resolve(self, request: Request) -> _Resolve: + path = request.rel_url.path_safe + method = request.method +- if not path.startswith(self._prefix2) and path != self._prefix: ++ # We normalise here to avoid matches that traverse below the static root. ++ # e.g. /static/../../../../home/user/webapp/static/ ++ norm_path = os.path.normpath(path) ++ if IS_WINDOWS: ++ norm_path = norm_path.replace("\\", "/") ++ if not norm_path.startswith(self._prefix2) and norm_path != self._prefix: + return None, set() + + allowed_methods = self._allowed_methods +@@ -666,14 +673,7 @@ class StaticResource(PrefixResource): + return iter(self._routes.values()) + + async def _handle(self, request: Request) -> StreamResponse: +- rel_url = request.match_info["filename"] +- filename = Path(rel_url) +- if filename.anchor: +- # rel_url is an absolute name like +- # /static/\\machine_name\c$ or /static/D:\path +- # where the static dir is totally different +- raise HTTPForbidden() +- ++ filename = request.match_info["filename"] + unresolved_path = self._directory.joinpath(filename) + loop = asyncio.get_running_loop() + return await loop.run_in_executor( +diff --git a/tests/test_urldispatch.py b/tests/test_urldispatch.py +index ba6bdff..e329ea2 100644 +--- a/tests/test_urldispatch.py ++++ b/tests/test_urldispatch.py +@@ -1,4 +1,5 @@ + import pathlib ++import platform + import re + from collections.abc import Container, Iterable, Mapping, MutableMapping, Sized + from typing import NoReturn +@@ -1041,7 +1042,22 @@ async def test_405_for_resource_adapter(router) -> None: + assert (None, {"HEAD", "GET"}) == ret + + +-async def test_check_allowed_method_for_found_resource(router) -> None: ++@pytest.mark.skipif(platform.system() == "Windows", reason="Different path formats") ++async def test_static_resource_outside_traversal(router: web.UrlDispatcher) -> None: ++ """Test relative path traversing outside root does not resolve.""" ++ static_file = pathlib.Path(aiohttp.__file__) ++ request_path = "/st" + "/.." * (len(static_file.parts) - 2) + str(static_file) ++ assert pathlib.Path(request_path).resolve() == static_file ++ ++ resource = router.add_static("/st", static_file.parent) ++ ret = await resource.resolve(make_mocked_request("GET", request_path)) ++ # Should not resolve, otherwise filesystem information may be leaked. ++ assert (None, set()) == ret ++ ++ ++async def test_check_allowed_method_for_found_resource( ++ router: web.UrlDispatcher, ++) -> None: + handler = make_handler() + resource = router.add_resource("/") + resource.add_route("GET", handler) +diff --git a/tests/test_web_sendfile_functional.py b/tests/test_web_sendfile_functional.py +index 0325a46..3207623 100644 +--- a/tests/test_web_sendfile_functional.py ++++ b/tests/test_web_sendfile_functional.py +@@ -638,7 +638,7 @@ async def test_static_file_directory_traversal_attack(aiohttp_client) -> None: + + url_abspath = "/static/" + str(full_path.resolve()) + resp = await client.get(url_abspath) +- assert 403 == resp.status ++ assert resp.status == 404 + await resp.release() + + await client.close() +diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py +index ee60b69..7de3ea5 100644 +--- a/tests/test_web_urldispatcher.py ++++ b/tests/test_web_urldispatcher.py +@@ -838,8 +838,8 @@ async def test_static_absolute_url( + here = pathlib.Path(__file__).parent + app.router.add_static("/static", here) + client = await aiohttp_client(app) +- resp = await client.get("/static/" + str(file_path.resolve())) +- assert resp.status == 403 ++ async with client.get("/static/" + str(file_path.resolve())) as resp: ++ assert resp.status == 404 + + + async def test_for_issue_5250( diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 9a45eecb8c..16429c9d86 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -6,6 +6,7 @@ LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=748073912af33aa59430d3702aa32d41" SRC_URI += "file://CVE-2025-69224.patch \ file://CVE-2025-69225.patch \ + file://CVE-2025-69226.patch \ " SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" From patchwork Wed Feb 4 16:29:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80439 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C31F8E9D410 for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24771.1770222570126619516 for ; Wed, 04 Feb 2026 08:29:30 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=A0j63MrC; spf=pass (domain: gmail.com, ip: 209.85.128.53, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-47ee2715254so39546945e9.3 for ; Wed, 04 Feb 2026 08:29:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222568; x=1770827368; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=eNyI1ZWbqGyxxFaWw0VIChXf5r10jPEenfV/FgnywUQ=; b=A0j63MrCbd/xXP/Jx/ei6O50tXVGiUCnkh5mjV8CegOC4wjBbhNrIhS9TSltzF2wLp CfTJNhkYlS1dVWZYTm3rFJY87w5diKvBSzxbA/tNQTN7sEwp5r/lNxj6+ARWVHjKVmYz SreT9ZHxhdd10AGG7oHPva9SgXo2is6pTV3Gnk3tbhtckpw34zYYEocR2BU+Rve4bBWQ FlVwhjlct6lcDcsp4VNbM5+iSWjOKkI8IN2EwKVBCl+vkFGUyRtKJ2/tA7QK2eGhxbnU BOxzm1Ky+0dEYKRolepiAEZtDNNhqaAUsqZVa6cacf0wTUuT43nwG29iZVa3ffiCJB0g 9raA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222568; x=1770827368; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=eNyI1ZWbqGyxxFaWw0VIChXf5r10jPEenfV/FgnywUQ=; b=B/9xUsE7jw97d1VeonPPDcC+v6PrAvWURIvGgWaYNqvBVEpWNocjzQ81Mc4VsV7y8v xVKkXqsEOybVS5rdMUG0bjur8tUiTHdzrCSdGZopGYNJ8m/foqWdOVBi4ZVRpaTnCqbZ 0QTbDlGfIgfiftEKQ1v6Iaa9FGTYA/K3hVJPL4TQWkL5CdjJ+dR+lcNrkeIu4W1Uer/q qIfrmRbZ8KKR+XBCRHqV62wp1WgF58x79p4J5w7wIu6ekd2YQuwSQnEnfwpeYf53uOXN RQxmtugsbafCXU6+t/w64wPz1FlnZyAityiEn3wPUG2FCtS00nRvBgDHiVjyWRsiMN23 BLBg== X-Gm-Message-State: AOJu0Ywa65FFNWbcLCMuTwVb90pXJNEu2ZRGljCHytM7yUcx7pOpL660 5Vedc7WakvKQDMG40g+m9/I5ztEOuhqmjiG/2v3tK3IoNP5T23r4nrgJzSFgCQ== X-Gm-Gg: AZuq6aJ/utarghGutL8rV2aV6eTTjWWn+N8tbIliwFDW/fJTgWVwy89hMRiqyATT6oL dRGQurhfIS6+fPSLetCsSezAzho3I98o48qx2nnjVm2JsUiaWsG7X64PZrnlJhnJqbffCxENLjO KEcxvfrPbwYvQOpNrD7OuezMhq9ILORJRhkmIZMSVMqT4tlaDTnH0IQGkEtl+ZaRSNMN+njNT9A uBtwXFRbKZ/cqw1PEAvYigzbS5iVjkMOJfqXx4ZwZnicFEF+e+wRxE0oVkCltldM4O0QAnto5T4 dWnuva+jIASdcYjMneEHOFCNAmzijVGv4JG9rDXWQ+U9Nb7UCMPl2/J43991jNLXb3grxg+gcj2 f/VOYVftzDDzgKvasj7cdWakl6MdfbY3uZ30h4lD+mz7WL3CcbiVH8ItKxfSh7jIodjcO2gT3wr r+oI0PoVpUWSVBIp27IOI= X-Received: by 2002:a05:600c:3106:b0:477:58:7cf4 with SMTP id 5b1f17b1804b1-4830e93e9b9mr45909215e9.4.1770222568262; Wed, 04 Feb 2026 08:29:28 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.27 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:27 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 4/7] python3-aiohttp: patch CVE-2025-69227 Date: Wed, 4 Feb 2026 17:29:19 +0100 Message-ID: <20260204162924.3042284-4-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124139 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69227 Backport the patch that is referenced by teh NVD advisory. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69227.patch | 148 ++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 1 + 2 files changed, 149 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69227.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69227.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69227.patch new file mode 100644 index 0000000000..65dae1707b --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69227.patch @@ -0,0 +1,148 @@ +From 635c8c03b609b1099d93fb8ea8c8691624237b0f Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 04:53:29 +0000 +Subject: [PATCH] Replace asserts with exceptions (#11897) (#11914) + +From: Sam Bull + +(cherry picked from commit d5bf65f15c0c718b6b95e9bc9d0914a92c51e60f) + +Co-authored-by: J. Nick Koston + +CVE: CVE-2025-69227 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/bc1319ec3cbff9438a758951a30907b072561259] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/multipart.py | 10 ++++------ + aiohttp/web_request.py | 8 +++----- + tests/test_multipart.py | 12 +++++++++++- + tests/test_web_request.py | 24 +++++++++++++++++++++++- + 4 files changed, 41 insertions(+), 13 deletions(-) + +diff --git a/aiohttp/multipart.py b/aiohttp/multipart.py +index 54dfd48..7783ac5 100644 +--- a/aiohttp/multipart.py ++++ b/aiohttp/multipart.py +@@ -357,11 +357,8 @@ class BodyPartReader: + self._read_bytes += len(chunk) + if self._read_bytes == self._length: + self._at_eof = True +- if self._at_eof: +- clrf = await self._content.readline() +- assert ( +- b"\r\n" == clrf +- ), "reader did not read all the data or it is malformed" ++ if self._at_eof and await self._content.readline() != b"\r\n": ++ raise ValueError("Reader did not read all the data or it is malformed") + return chunk + + async def _read_chunk_from_length(self, size: int) -> bytes: +@@ -390,7 +387,8 @@ class BodyPartReader: + while len(chunk) < self._boundary_len: + chunk += await self._content.read(size) + self._content_eof += int(self._content.at_eof()) +- assert self._content_eof < 3, "Reading after EOF" ++ if self._content_eof > 2: ++ raise ValueError("Reading after EOF") + if self._content_eof: + break + if len(chunk) > size: +diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py +index 6e09027..96222b0 100644 +--- a/aiohttp/web_request.py ++++ b/aiohttp/web_request.py +@@ -721,13 +721,13 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin): + multipart = await self.multipart() + max_size = self._client_max_size + +- field = await multipart.next() +- while field is not None: ++ while (field := await multipart.next()) is not None: + size = 0 + field_ct = field.headers.get(hdrs.CONTENT_TYPE) + + if isinstance(field, BodyPartReader): +- assert field.name is not None ++ if field.name is None: ++ raise ValueError("Multipart field missing name.") + + # Note that according to RFC 7578, the Content-Type header + # is optional, even for files, so we can't assume it's +@@ -779,8 +779,6 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin): + raise ValueError( + "To decode nested multipart you need to use custom reader", + ) +- +- field = await multipart.next() + else: + data = await self.read() + if data: +diff --git a/tests/test_multipart.py b/tests/test_multipart.py +index 75b73a7..5351945 100644 +--- a/tests/test_multipart.py ++++ b/tests/test_multipart.py +@@ -221,11 +221,21 @@ class TestPartReader: + with Stream(data) as stream: + obj = aiohttp.BodyPartReader(BOUNDARY, {}, stream) + result = b"" +- with pytest.raises(AssertionError): ++ with pytest.raises(ValueError): + for _ in range(4): + result += await obj.read_chunk(7) + assert data == result + ++ async def test_read_with_content_length_malformed_crlf(self) -> None: ++ # Content-Length is correct but data after content is not \r\n ++ content = b"Hello" ++ h = CIMultiDictProxy(CIMultiDict({"CONTENT-LENGTH": str(len(content))})) ++ # Malformed: "XX" instead of "\r\n" after content ++ with Stream(content + b"XX--:--") as stream: ++ obj = aiohttp.BodyPartReader(BOUNDARY, h, stream) ++ with pytest.raises(ValueError, match="malformed"): ++ await obj.read() ++ + async def test_read_boundary_with_incomplete_chunk(self) -> None: + with Stream(b"") as stream: + +diff --git a/tests/test_web_request.py b/tests/test_web_request.py +index da80ca9..125b95e 100644 +--- a/tests/test_web_request.py ++++ b/tests/test_web_request.py +@@ -10,6 +10,7 @@ from multidict import CIMultiDict, CIMultiDictProxy, MultiDict + from yarl import URL + + from aiohttp import HttpVersion ++from aiohttp.base_protocol import BaseProtocol + from aiohttp.http_parser import RawRequestMessage + from aiohttp.streams import StreamReader + from aiohttp.test_utils import make_mocked_request +@@ -815,7 +816,28 @@ async def test_multipart_formdata(protocol) -> None: + assert dict(result) == {"a": "b", "c": "d"} + + +-async def test_multipart_formdata_file(protocol) -> None: ++async def test_multipart_formdata_field_missing_name(protocol: BaseProtocol) -> None: ++ # Ensure ValueError is raised when Content-Disposition has no name ++ payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) ++ payload.feed_data( ++ b"-----------------------------326931944431359\r\n" ++ b"Content-Disposition: form-data\r\n" # Missing name! ++ b"\r\n" ++ b"value\r\n" ++ b"-----------------------------326931944431359--\r\n" ++ ) ++ content_type = ( ++ "multipart/form-data; boundary=---------------------------326931944431359" ++ ) ++ payload.feed_eof() ++ req = make_mocked_request( ++ "POST", "/", headers={"CONTENT-TYPE": content_type}, payload=payload ++ ) ++ with pytest.raises(ValueError, match="Multipart field missing name"): ++ await req.post() ++ ++ ++async def test_multipart_formdata_file(protocol: BaseProtocol) -> None: + # Make sure file uploads work, even without a content type + payload = StreamReader(protocol, 2**16, loop=asyncio.get_event_loop()) + payload.feed_data( diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 16429c9d86..644c07153d 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -7,6 +7,7 @@ LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=748073912af33aa59430d3702aa32d41" SRC_URI += "file://CVE-2025-69224.patch \ file://CVE-2025-69225.patch \ file://CVE-2025-69226.patch \ + file://CVE-2025-69227.patch \ " SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" From patchwork Wed Feb 4 16:29:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80442 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8A55E9D416 for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24637.1770222570784365606 for ; Wed, 04 Feb 2026 08:29:31 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=XnDSXRpz; spf=pass (domain: gmail.com, ip: 209.85.128.44, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-4807068eacbso59457495e9.2 for ; Wed, 04 Feb 2026 08:29:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222569; x=1770827369; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=t0poR2kUSbCsdx8dbzV8fYNFDd4ioGjCw4zOOARr/w0=; b=XnDSXRpzOxRe89Hdo2tzD4A7kE2sXdLEFQKizPqNh3Ft8ksvSekUVVKtHqzjt4TDcP vbh7HGwKqcPkWqPJRBnvG4sOP4NyNxJ4AiGYdkng14+FUUSIHtBcyw7Q+Z8feBGW7YcO UbqrZvGcV92So3JkmhNetjbFCm/emS2Js13XFWLcKqvMYmiYYLPPJ1i07u5eBfaTDmUP sWyOx2viAEQ+twJkgY3yI0C9pze7L/12fAk3+W/QYx6i9QhecWiDRKBYJTptXQOPxpLK H+iW36nziYKPzSlze4s2S54gtH66O9vDzfSKvvHDov8rDyaVWFioCl7sMXHD/cosaeZH YCcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222569; x=1770827369; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=t0poR2kUSbCsdx8dbzV8fYNFDd4ioGjCw4zOOARr/w0=; b=fGlKUJmV9FMwLyn+/6GsfN7BfoNS6vfgDiIZJJvzUzCQBxfOkI9jHpiN/ctmz/FeOZ eT5kl4WNeCJ9aaBNC0TgyhujmofUd4djpbIXs9d+T14IKE7YjcV+6+o684232FwcTtn/ 7/6r/e/DiXhTysQscb1UuGs+5nyi+EWwhawHTQ1AAuYRCqZ4bgP5j/8E/8ac2upAZe/7 kg/WbdfFp2Jj1Ui4ZbrOCoZ+7Sq0J3CK9DCXPdVe82pvaoB9Ppej3LjbZWgmxLzhDx3s ieX0kLtr7ggRtRw+fLNpxRgJ49AUgIwBK1is4S+00hO9v2tBYXLdyUwQkbIuoDUBnpfo 7uMw== X-Gm-Message-State: AOJu0YyvzZarlnTdQXOcqFgoehwgHJWUgRKL6jdawQ4hTAufEE0NgbVC w8t51O64rjJe9nBR59B9S25/Ulmi730/jETK6YiEPg+8xDFG2AWxd3nTcWP0Jg== X-Gm-Gg: AZuq6aJu5afYS+jeJEZgYdgeNY946hV5w7nVCsibyQjmVz6kWN18n0CsxXblE88fzyd ZIzrDc/HXCjPDQg3EjtMUQ0Ai5AwSWIF6sxy5uuEqHsOcHM1SbwcsU3JrLWlxuZ1+7CJeVBnMZv B1xnMa/WMeK+UNZ/7TlPpI8DkZHrVDIajkWKYjHpWtJpL0KMoVxudkmr07iDQDWKmdg6jfgQUFs iDP954QV/quM/DAlGgT0eNHoHkr0RIaxQ7OlHNFbd8HcYvxjJJgCkDYsVupYxtzibI9ao7sdsgc OLqVkikXyMLFltAtTsuQOvRZKAOhVQ4UlMCv9BxAjCd2LSFkdqlUfmBf8qTjakSFs1JW6DFC7EH NGokKZf1NEzuAlFi3hNPIXqU2ONEJzif4IFgdRsmHLaT0ttB3mvZ3Dih7rWHGjPM7gerdxa/ni8 cISvEcSjV6 X-Received: by 2002:a05:600c:1c28:b0:477:7925:f7fb with SMTP id 5b1f17b1804b1-4830e93203cmr54405675e9.10.1770222568980; Wed, 04 Feb 2026 08:29:28 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.28 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:28 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 5/7] python3-aiohttp: patch CVE-2025-69228 Date: Wed, 4 Feb 2026 17:29:20 +0100 Message-ID: <20260204162924.3042284-5-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124140 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69228 Backport the patch that is referenced by the NVD advisory. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69228.patch | 47 +++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 1 + 2 files changed, 48 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69228.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69228.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69228.patch new file mode 100644 index 0000000000..74e383ea1b --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69228.patch @@ -0,0 +1,47 @@ +From 8426e0e6df8a3481c7482d4fbce749bfe77e2e44 Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 02:48:45 +0000 +Subject: [PATCH] Enforce client_max_size over entire multipart form (#11889) + (#11908) + +From: Sam Bull + +(cherry picked from commit ed90718fab5d34c127a283e10385f19440df7dd0) + +CVE: CVE-2025-69228 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/b7dbd35375aedbcd712cbae8ad513d56d11cce60] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/web_request.py | 2 +- + tests/test_web_functional.py | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py +index 96222b0..b5fa40c 100644 +--- a/aiohttp/web_request.py ++++ b/aiohttp/web_request.py +@@ -721,8 +721,8 @@ class BaseRequest(MutableMapping[str, Any], HeadersMixin): + multipart = await self.multipart() + max_size = self._client_max_size + ++ size = 0 + while (field := await multipart.next()) is not None: +- size = 0 + field_ct = field.headers.get(hdrs.CONTENT_TYPE) + + if isinstance(field, BodyPartReader): +diff --git a/tests/test_web_functional.py b/tests/test_web_functional.py +index c33b3ce..8ec237b 100644 +--- a/tests/test_web_functional.py ++++ b/tests/test_web_functional.py +@@ -1705,8 +1705,8 @@ async def test_app_max_client_size(aiohttp_client) -> None: + await resp.release() + + +-async def test_app_max_client_size_adjusted(aiohttp_client) -> None: +- async def handler(request): ++async def test_app_max_client_size_adjusted(aiohttp_client: AiohttpClient) -> None: ++ async def handler(request: web.Request) -> web.Response: + await request.post() + return web.Response(body=b"ok") + diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 644c07153d..55ff57d05c 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -8,6 +8,7 @@ SRC_URI += "file://CVE-2025-69224.patch \ file://CVE-2025-69225.patch \ file://CVE-2025-69226.patch \ file://CVE-2025-69227.patch \ + file://CVE-2025-69228.patch \ " SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" From patchwork Wed Feb 4 16:29:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CDFABE9D414 for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.24638.1770222572019427869 for ; Wed, 04 Feb 2026 08:29:32 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=e3PLNqOU; spf=pass (domain: gmail.com, ip: 209.85.128.47, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4806dffc64cso8430325e9.1 for ; Wed, 04 Feb 2026 08:29:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222570; x=1770827370; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FEyvX+RX0DkJBR4yNvVoyJhxRTmtrCn9YFDsR694Elo=; b=e3PLNqOU2WJvEyemYukdgA+QO/rIdVyjkNAmk8AV9Vj/tOAJn/b4AAx7PwpT/bnmPG QFl5Cf3+DRmeVYifnolu0jmbEQ1qXRzVL5ARbc9X/2J2ZbuEgtFskEbbepcoEJxbT2HK GvsSQIMtz9anXTxUzX+Yl9PYQaX3rdTptJw0r/+f1EUbbcjkV4ZKY4JLJbRlLzXC1LEx hVnb5a3updszhq2qJ5FPJ/c2t5Aw9EvRf2+yOqCIcWRiAnsNO2qAhHyRqk8hVwE5XH3g 2BdU460P9smMfE4nz01/ucZLbQ11/noeS8EIKpiagJKeYBZzfydyyJolbDUpM1XW//G2 6mNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222570; x=1770827370; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=FEyvX+RX0DkJBR4yNvVoyJhxRTmtrCn9YFDsR694Elo=; b=QMMoUHZUdNfd7Uq3W+IFbcG3/g7n/lgluUsvu/mqOWUbDwoIsCsTsO0K0pe0DTuoSR L/UWq8GLbjC/I4WXb2SnEgUYTIAwGUzJKMK+thAKqACLh1UBue2UukoxCx2mvsiHVYox eCa2Fhk0KmyZfXAR0ypc5tMyiF+eP62xCP8F5HgvGQrhCgrQCfIjwu7qKLspBNWIQ3Ku TWClemXslK98Y7nuPlFfBdvz8GxFcIy1eiJnhOAf7qFd1QaKI1Y0Zkd6aKj55umlNYFx 35e4ngwOiMrVFo9UMvp9BRqq9BHl8LexBvEUoVM5wqFuNRkTdxBbvPyqu0YBJm/ftvu2 fNTQ== X-Gm-Message-State: AOJu0Yz7DM80b6HCysNfkMne+QLzSMyJFFRDuapU5RULYjaOzwoO6hn/ IG8fU1q61e0fQbY+UOm4tK6x16WB42LuIyrBdzSwhB3CxwNWzVS6Rk/zQl3emQ== X-Gm-Gg: AZuq6aJCsvvFCyERlVB+rT1zYSjW1bbiOPlbepzJYzHci8JvLb4SFoD2MruPnUSnN4M lViLwt6Mp4SLCiMtvpILEBo7g7WqbCI17aUDJpNP6VO9iFC4GXYZ412VLFAGNsysKOGZtHM4mJ0 afvl7aornEvYTxqb2LH5rWRbXKvc5o7MVdTlOL5txnx3LCs87UUHOGI0jEPpBE3GGmxq5pF9TL2 OSXKoBVH4QoCV2uKwGxVaQIFk7P5oeqty9vxlDPbpTRZBbRJVlOY8l2MLbfUFV1GiALTauuRpEA JUDsn6iaJC4H4CYB6MR864DegOVz3Zw5/eFV6cn+drFSDWgwYdOTPFu5eGgpbm7hS1VekomIOWn xCWv3oqQkye2VJPs2HgibvLK5rklfKbfCzqyEoQ8/hotsQZ9uZ1R22+d+JxpprODyqJNT0yDF/t W3Bpz26sh7 X-Received: by 2002:a05:600c:5250:b0:46e:32dd:1b1a with SMTP id 5b1f17b1804b1-4830e925fdemr49092775e9.7.1770222569854; Wed, 04 Feb 2026 08:29:29 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:29 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 6/7] python3-aiohttp: patch CVE-2025-69229 Date: Wed, 4 Feb 2026 17:29:21 +0100 Message-ID: <20260204162924.3042284-6-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124141 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69229 Backport the patches referenced by the NVD advisory. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69229-1.patch | 111 ++++++++ .../python3-aiohttp/CVE-2025-69229-2.patch | 255 ++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 2 + 3 files changed, 368 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-1.patch create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-2.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-1.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-1.patch new file mode 100644 index 0000000000..70feb03258 --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-1.patch @@ -0,0 +1,111 @@ +From 9e03b5732805f3cf3c5c249761e2fb8ace2223d3 Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 03:57:17 +0000 +Subject: [PATCH 1/2] Use collections.deque for chunk splits (#11892) (#11912) + +From: Sam Bull + +(cherry picked from commit 271532ea355c65480c8ecc14137dfbb72aec8f6f) + +--------- + +Co-authored-by: Finder + +CVE: CVE-2025-69229 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/dc3170b56904bdf814228fae70a5501a42a6c712] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/streams.py | 8 ++++---- + tests/test_http_parser.py | 14 +++++++++----- + 2 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/aiohttp/streams.py b/aiohttp/streams.py +index 7a3f64d..108257e 100644 +--- a/aiohttp/streams.py ++++ b/aiohttp/streams.py +@@ -148,7 +148,7 @@ class StreamReader(AsyncStreamReaderMixin): + self._loop = loop + self._size = 0 + self._cursor = 0 +- self._http_chunk_splits: Optional[List[int]] = None ++ self._http_chunk_splits: Optional[Deque[int]] = None + self._buffer: Deque[bytes] = collections.deque() + self._buffer_offset = 0 + self._eof = False +@@ -295,7 +295,7 @@ class StreamReader(AsyncStreamReaderMixin): + raise RuntimeError( + "Called begin_http_chunk_receiving when some data was already fed" + ) +- self._http_chunk_splits = [] ++ self._http_chunk_splits = collections.deque() + + def end_http_chunk_receiving(self) -> None: + if self._http_chunk_splits is None: +@@ -454,7 +454,7 @@ class StreamReader(AsyncStreamReaderMixin): + raise self._exception + + while self._http_chunk_splits: +- pos = self._http_chunk_splits.pop(0) ++ pos = self._http_chunk_splits.popleft() + if pos == self._cursor: + return (b"", True) + if pos > self._cursor: +@@ -527,7 +527,7 @@ class StreamReader(AsyncStreamReaderMixin): + chunk_splits = self._http_chunk_splits + # Prevent memory leak: drop useless chunk splits + while chunk_splits and chunk_splits[0] < self._cursor: +- chunk_splits.pop(0) ++ chunk_splits.popleft() + + if self._size < self._low_water and self._protocol._reading_paused: + self._protocol.resume_reading() +diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py +index d4c1768..b9d917f 100644 +--- a/tests/test_http_parser.py ++++ b/tests/test_http_parser.py +@@ -1223,7 +1223,8 @@ def test_http_request_chunked_payload(parser) -> None: + parser.feed_data(b"4\r\ndata\r\n4\r\nline\r\n0\r\n\r\n") + + assert b"dataline" == b"".join(d for d in payload._buffer) +- assert [4, 8] == payload._http_chunk_splits ++ assert payload._http_chunk_splits is not None ++ assert [4, 8] == list(payload._http_chunk_splits) + assert payload.is_eof() + + +@@ -1238,7 +1239,8 @@ def test_http_request_chunked_payload_and_next_message(parser) -> None: + ) + + assert b"dataline" == b"".join(d for d in payload._buffer) +- assert [4, 8] == payload._http_chunk_splits ++ assert payload._http_chunk_splits is not None ++ assert [4, 8] == list(payload._http_chunk_splits) + assert payload.is_eof() + + assert len(messages) == 1 +@@ -1262,12 +1264,13 @@ def test_http_request_chunked_payload_chunks(parser) -> None: + parser.feed_data(b"test: test\r\n") + + assert b"dataline" == b"".join(d for d in payload._buffer) +- assert [4, 8] == payload._http_chunk_splits ++ assert payload._http_chunk_splits is not None ++ assert [4, 8] == list(payload._http_chunk_splits) + assert not payload.is_eof() + + parser.feed_data(b"\r\n") + assert b"dataline" == b"".join(d for d in payload._buffer) +- assert [4, 8] == payload._http_chunk_splits ++ assert [4, 8] == list(payload._http_chunk_splits) + assert payload.is_eof() + + +@@ -1278,7 +1281,8 @@ def test_parse_chunked_payload_chunk_extension(parser) -> None: + parser.feed_data(b"4;test\r\ndata\r\n4\r\nline\r\n0\r\ntest: test\r\n\r\n") + + assert b"dataline" == b"".join(d for d in payload._buffer) +- assert [4, 8] == payload._http_chunk_splits ++ assert payload._http_chunk_splits is not None ++ assert [4, 8] == list(payload._http_chunk_splits) + assert payload.is_eof() + + diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-2.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-2.patch new file mode 100644 index 0000000000..e67832f09e --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69229-2.patch @@ -0,0 +1,255 @@ +From e124809ca5f17e608c09fc79423f9c357208a3c5 Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 15:23:14 +0000 +Subject: [PATCH 2/2] Limit number of chunks before pausing reading (#11894) + (#11916) + +From: Sam Bull + +(cherry picked from commit 1e4120e87daec963c67f956111e6bca44d7c3dea) + +Co-authored-by: J. Nick Koston + +CVE: CVE-2025-69229 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/4ed97a4e46eaf61bd0f05063245f613469700229] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/streams.py | 25 ++++++- + tests/test_streams.py | 170 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 194 insertions(+), 1 deletion(-) + +diff --git a/aiohttp/streams.py b/aiohttp/streams.py +index 108257e..9329534 100644 +--- a/aiohttp/streams.py ++++ b/aiohttp/streams.py +@@ -116,6 +116,8 @@ class StreamReader(AsyncStreamReaderMixin): + "_protocol", + "_low_water", + "_high_water", ++ "_low_water_chunks", ++ "_high_water_chunks", + "_loop", + "_size", + "_cursor", +@@ -145,6 +147,11 @@ class StreamReader(AsyncStreamReaderMixin): + self._high_water = limit * 2 + if loop is None: + loop = asyncio.get_event_loop() ++ # Ensure high_water_chunks >= 3 so it's always > low_water_chunks. ++ self._high_water_chunks = max(3, limit // 4) ++ # Use max(2, ...) because there's always at least 1 chunk split remaining ++ # (the current position), so we need low_water >= 2 to allow resume. ++ self._low_water_chunks = max(2, self._high_water_chunks // 2) + self._loop = loop + self._size = 0 + self._cursor = 0 +@@ -321,6 +328,15 @@ class StreamReader(AsyncStreamReaderMixin): + + self._http_chunk_splits.append(self.total_bytes) + ++ # If we get too many small chunks before self._high_water is reached, then any ++ # .read() call becomes computationally expensive, and could block the event loop ++ # for too long, hence an additional self._high_water_chunks here. ++ if ( ++ len(self._http_chunk_splits) > self._high_water_chunks ++ and not self._protocol._reading_paused ++ ): ++ self._protocol.pause_reading() ++ + # wake up readchunk when end of http chunk received + waiter = self._waiter + if waiter is not None: +@@ -529,7 +545,14 @@ class StreamReader(AsyncStreamReaderMixin): + while chunk_splits and chunk_splits[0] < self._cursor: + chunk_splits.popleft() + +- if self._size < self._low_water and self._protocol._reading_paused: ++ if ( ++ self._protocol._reading_paused ++ and self._size < self._low_water ++ and ( ++ self._http_chunk_splits is None ++ or len(self._http_chunk_splits) < self._low_water_chunks ++ ) ++ ): + self._protocol.resume_reading() + return data + +diff --git a/tests/test_streams.py b/tests/test_streams.py +index 1b65f77..c5bc671 100644 +--- a/tests/test_streams.py ++++ b/tests/test_streams.py +@@ -1552,3 +1552,173 @@ async def test_stream_reader_iter_chunks_chunked_encoding(protocol) -> None: + + def test_isinstance_check() -> None: + assert isinstance(streams.EMPTY_PAYLOAD, streams.StreamReader) ++ ++ ++async def test_stream_reader_pause_on_high_water_chunks( ++ protocol: mock.Mock, ++) -> None: ++ """Test that reading is paused when chunk count exceeds high water mark.""" ++ loop = asyncio.get_event_loop() ++ # Use small limit so high_water_chunks is small: limit // 4 = 10 ++ stream = streams.StreamReader(protocol, limit=40, loop=loop) ++ ++ assert stream._high_water_chunks == 10 ++ assert stream._low_water_chunks == 5 ++ ++ # Feed chunks until we exceed high_water_chunks ++ for i in range(12): ++ stream.begin_http_chunk_receiving() ++ stream.feed_data(b"x") # 1 byte per chunk ++ stream.end_http_chunk_receiving() ++ ++ # pause_reading should have been called when chunk count exceeded 10 ++ protocol.pause_reading.assert_called() ++ ++ ++async def test_stream_reader_resume_on_low_water_chunks( ++ protocol: mock.Mock, ++) -> None: ++ """Test that reading resumes when chunk count drops below low water mark.""" ++ loop = asyncio.get_event_loop() ++ # Use small limit so high_water_chunks is small: limit // 4 = 10 ++ stream = streams.StreamReader(protocol, limit=40, loop=loop) ++ ++ assert stream._high_water_chunks == 10 ++ assert stream._low_water_chunks == 5 ++ ++ # Feed chunks until we exceed high_water_chunks ++ for i in range(12): ++ stream.begin_http_chunk_receiving() ++ stream.feed_data(b"x") # 1 byte per chunk ++ stream.end_http_chunk_receiving() ++ ++ # Simulate that reading was paused ++ protocol._reading_paused = True ++ protocol.pause_reading.reset_mock() ++ ++ # Read data to reduce both size and chunk count ++ # Reading will consume chunks and reduce _http_chunk_splits ++ data = await stream.read(10) ++ assert data == b"xxxxxxxxxx" ++ ++ # resume_reading should have been called when both size and chunk count ++ # dropped below their respective low water marks ++ protocol.resume_reading.assert_called() ++ ++ ++async def test_stream_reader_no_resume_when_chunks_still_high( ++ protocol: mock.Mock, ++) -> None: ++ """Test that reading doesn't resume if chunk count is still above low water.""" ++ loop = asyncio.get_event_loop() ++ # Use small limit so high_water_chunks is small: limit // 4 = 10 ++ stream = streams.StreamReader(protocol, limit=40, loop=loop) ++ ++ # Feed many chunks ++ for i in range(12): ++ stream.begin_http_chunk_receiving() ++ stream.feed_data(b"x") ++ stream.end_http_chunk_receiving() ++ ++ # Simulate that reading was paused ++ protocol._reading_paused = True ++ ++ # Read only a few bytes - chunk count will still be high ++ data = await stream.read(2) ++ assert data == b"xx" ++ ++ # resume_reading should NOT be called because chunk count is still >= low_water_chunks ++ protocol.resume_reading.assert_not_called() ++ ++ ++async def test_stream_reader_read_non_chunked_response( ++ protocol: mock.Mock, ++) -> None: ++ """Test that non-chunked responses work correctly (no chunk tracking).""" ++ loop = asyncio.get_event_loop() ++ stream = streams.StreamReader(protocol, limit=40, loop=loop) ++ ++ # Non-chunked: just feed data without begin/end_http_chunk_receiving ++ stream.feed_data(b"Hello World") ++ ++ # _http_chunk_splits should be None for non-chunked responses ++ assert stream._http_chunk_splits is None ++ ++ # Reading should work without issues ++ data = await stream.read(5) ++ assert data == b"Hello" ++ ++ data = await stream.read(6) ++ assert data == b" World" ++ ++ ++async def test_stream_reader_resume_non_chunked_when_paused( ++ protocol: mock.Mock, ++) -> None: ++ """Test that resume works for non-chunked responses when paused due to size.""" ++ loop = asyncio.get_event_loop() ++ # Small limit so we can trigger pause via size ++ stream = streams.StreamReader(protocol, limit=10, loop=loop) ++ ++ # Feed data that exceeds high_water (limit * 2 = 20) ++ stream.feed_data(b"x" * 25) ++ ++ # Simulate that reading was paused due to size ++ protocol._reading_paused = True ++ protocol.pause_reading.assert_called() ++ ++ # Read enough to drop below low_water (limit = 10) ++ data = await stream.read(20) ++ assert data == b"x" * 20 ++ ++ # resume_reading should be called (size is now 5 < low_water 10) ++ protocol.resume_reading.assert_called() ++ ++ ++@pytest.mark.parametrize("limit", [1, 2, 4]) ++async def test_stream_reader_small_limit_resumes_reading( ++ protocol: mock.Mock, ++ limit: int, ++) -> None: ++ """Test that small limits still allow resume_reading to be called. ++ ++ Even with very small limits, high_water_chunks should be at least 3 ++ and low_water_chunks should be at least 2, with high > low to ensure ++ proper flow control. ++ """ ++ loop = asyncio.get_event_loop() ++ stream = streams.StreamReader(protocol, limit=limit, loop=loop) ++ ++ # Verify minimum thresholds are enforced and high > low ++ assert stream._high_water_chunks >= 3 ++ assert stream._low_water_chunks >= 2 ++ assert stream._high_water_chunks > stream._low_water_chunks ++ ++ # Set up pause/resume side effects ++ def pause_reading() -> None: ++ protocol._reading_paused = True ++ ++ protocol.pause_reading.side_effect = pause_reading ++ ++ def resume_reading() -> None: ++ protocol._reading_paused = False ++ ++ protocol.resume_reading.side_effect = resume_reading ++ ++ # Feed 4 chunks (triggers pause at > high_water_chunks which is >= 3) ++ for char in b"abcd": ++ stream.begin_http_chunk_receiving() ++ stream.feed_data(bytes([char])) ++ stream.end_http_chunk_receiving() ++ ++ # Reading should now be paused ++ assert protocol._reading_paused is True ++ assert protocol.pause_reading.called ++ ++ # Read all data - should resume (chunk count drops below low_water_chunks) ++ data = stream.read_nowait() ++ assert data == b"abcd" ++ assert stream._size == 0 ++ ++ protocol.resume_reading.assert_called() ++ assert protocol._reading_paused is False diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 55ff57d05c..84dd369753 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -9,6 +9,8 @@ SRC_URI += "file://CVE-2025-69224.patch \ file://CVE-2025-69226.patch \ file://CVE-2025-69227.patch \ file://CVE-2025-69228.patch \ + file://CVE-2025-69229-1.patch \ + file://CVE-2025-69229-2.patch \ " SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2" From patchwork Wed Feb 4 16:29:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyorgy Sarvari X-Patchwork-Id: 80437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 879A8E9D40D for ; Wed, 4 Feb 2026 16:29:38 +0000 (UTC) Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.24772.1770222572508737797 for ; Wed, 04 Feb 2026 08:29:32 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20230601 header.b=RP03BFYL; spf=pass (domain: gmail.com, ip: 209.85.128.48, mailfrom: skandigraun@gmail.com) Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-47ee07570deso60119135e9.1 for ; Wed, 04 Feb 2026 08:29:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770222571; x=1770827371; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=uAVLIOe4T6ysRaNjtcm21azfsFJG6l2Sd25BlyIZhiM=; b=RP03BFYLXiOGnA+ESxMwyTT76n9/eVDihxrG4r/a3xWhDNprlD/g9S4CHoZsmYiD3B Z+g8VbgtYVuMKeDoWaB1vNctuF5fOCwM4Fja+z0KBiVpW0+8oz/702vN31PddLkqahRE 41GK9JdX/mabxNMI1Zu2qRYBrcDcXDamDgND81tygr8ei4WOYGB4osgc/5RGUEefFoCZ sYkjsUFkd5OJ+++CBCRZFk14IomPD9cWkGsSv7JwGClPWJ7BIqvzhW0zyWadmP9BFu5o JCxE86+Zzhb64c+/0dSwLA96kE+FcztMmkCyu44rZZoR4DDI1GAsg2WW1vKrgfaemG3/ 36rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770222571; x=1770827371; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=uAVLIOe4T6ysRaNjtcm21azfsFJG6l2Sd25BlyIZhiM=; b=AuQLvGUgSKYBhFWQmp0+nxBkLhrLheMU2gtnGV9HLzgRd7JYZ0HFxeGfYEOp32dnKm 1Ze9nzVPYFKLn8OkXcghac7JO6G/hkjl3PfEjH3yExBfmjhGZJKP8KzlMcpyMoABHt+U sEgi0415m62jKm2747HpMXlCQSO/ys21HXsHdDZZANVqu6hMNQJjk7cZT8qAwI5jq4mS 5uUAoF/9bjDkBhPPFzue3Yy2k4b36dAdjPHY0gAKVzUwxGcm7zvLwgZ+wIS4B1iZSeUH bkTfp+1j9RBFfvHEDkKhcqKK/DpR3aIXVCcpMooYyRqSlDlvmGYUiA8BJFEHV6dPyEgf 3zVg== X-Gm-Message-State: AOJu0YwKI5G0nK+svuX9+NFc6kdCDQzimCaU0N/t/mury9fsrVMH5MU4 UtVEQNZcaR8UqcmVOcyBuCqtT9kH3aHPJnOvrQzh9XCBd5YPg1nnt/SCgUGwCw== X-Gm-Gg: AZuq6aJQA57y+2rsetfmBS3G7Hho9fc2PjTiocwHMRTR+mVGtQbvhUCFaPHS3t8msuX w/crEQe86Ppwx7D6+JDzqPlzRTgrqakpXJ46A9gPeezCYHGW+X7b+iyharGkQsfbO6fTUnQldKX z5+hfVp7P6f/EbWoIy7o+/dK+LPIAStjWcga6XGnUVp5MHoJnz11doycJuCKtIlBZdUkXtOIcsf YYhE2ILt6L12CPzAMPUU09DOxvIKBUxNjRqbOXBQv8RgSOUjWBlzzDySCmkUDRIiAzCFpVq1owL nqFn7a2LUvwlBn9aiLpetuaWqLfKWZyT6GGGaB0bKUP8Gm7GXClQz/+42LwKoUIhu3GgcobmeQG me0/WZjwkkW79uUjU0rizGrLZrsloU3qhUeel4vk08rzC/iejZ6/gmIt2qD3gpea4ZS67aOF4yz T96HuJEdGI X-Received: by 2002:a05:600c:4e4f:b0:482:ef72:5787 with SMTP id 5b1f17b1804b1-4830e93eb28mr50248705e9.1.1770222570682; Wed, 04 Feb 2026 08:29:30 -0800 (PST) Received: from desktop ([51.154.145.205]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4830ec6fc89sm23293325e9.6.2026.02.04.08.29.30 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Feb 2026 08:29:30 -0800 (PST) From: Gyorgy Sarvari To: openembedded-devel@lists.openembedded.org Subject: [meta-python][whinlatter][PATCH 7/7] python3-aiohttp: patch CVE-2025-69230 Date: Wed, 4 Feb 2026 17:29:22 +0100 Message-ID: <20260204162924.3042284-7-skandigraun@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260204162924.3042284-1-skandigraun@gmail.com> References: <20260204162924.3042284-1-skandigraun@gmail.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Wed, 04 Feb 2026 16:29:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-devel/message/124142 Details: https://nvd.nist.gov/vuln/detail/CVE-2025-69230 Backport the patch referenced by the NVD advisory. The tests were only partially backported, as the original patch touched some tests that don't exist in this version. Signed-off-by: Gyorgy Sarvari --- .../python3-aiohttp/CVE-2025-69230.patch | 85 +++++++++++++++++++ .../python/python3-aiohttp_3.12.15.bb | 1 + 2 files changed, 86 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69230.patch diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69230.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69230.patch new file mode 100644 index 0000000000..46f91b70ab --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-69230.patch @@ -0,0 +1,85 @@ +From 811f8df8521b0850f5c79931e2e8c17113dda421 Mon Sep 17 00:00:00 2001 +From: Gyorgy Sarvari +Date: Sat, 3 Jan 2026 02:53:03 +0000 +Subject: [PATCH] Log once per cookie header (#11909) + +From: patchback[bot] <45432694+patchback[bot]@users.noreply.github.com> + +**This is a backport of PR #11890 as merged into master +(384a173022c9d057110c1418c5c4ff83a321900f).** + +Co-authored-by: Sam Bull + +CVE: CVE-2025-69230 +Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/64629a0834f94e46d9881f4e99c41a137e1f3326] +Signed-off-by: Gyorgy Sarvari +--- + aiohttp/_cookie_helpers.py | 8 +++++++- + tests/test_cookie_helpers.py | 8 ++++++-- + tests/test_web_request.py | 17 +++++++++++++++++ + 3 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/aiohttp/_cookie_helpers.py b/aiohttp/_cookie_helpers.py +index 4e9fc96..4edaa31 100644 +--- a/aiohttp/_cookie_helpers.py ++++ b/aiohttp/_cookie_helpers.py +@@ -181,6 +181,7 @@ def parse_cookie_header(header: str) -> List[Tuple[str, Morsel[str]]]: + i = 0 + n = len(header) + ++ invalid_names = [] + while i < n: + # Use the same pattern as parse_set_cookie_headers to find cookies + match = _COOKIE_PATTERN.match(header, i) +@@ -193,7 +194,7 @@ def parse_cookie_header(header: str) -> List[Tuple[str, Morsel[str]]]: + + # Validate the name + if not key or not _COOKIE_NAME_RE.match(key): +- internal_logger.warning("Can not load cookie: Illegal cookie name %r", key) ++ invalid_names.append(key) + continue + + # Create new morsel +@@ -209,6 +210,11 @@ def parse_cookie_header(header: str) -> List[Tuple[str, Morsel[str]]]: + + cookies.append((key, morsel)) + ++ if invalid_names: ++ internal_logger.debug( ++ "Cannot load cookie. Illegal cookie names: %r", invalid_names ++ ) ++ + return cookies + + +diff --git a/tests/test_cookie_helpers.py b/tests/test_cookie_helpers.py +index 6deef65..28addb2 100644 +--- a/tests/test_cookie_helpers.py ++++ b/tests/test_cookie_helpers.py +@@ -1,5 +1,7 @@ + """Tests for internal cookie helper functions.""" + ++import logging ++ + from http.cookies import ( + CookieError, + Morsel, +@@ -1374,14 +1376,16 @@ def test_parse_cookie_header_illegal_names(caplog: pytest.LogCaptureFixture) -> + """Test parse_cookie_header warns about illegal cookie names.""" + # Cookie name with comma (not allowed in _COOKIE_NAME_RE) + header = "good=value; invalid,cookie=bad; another=test" +- result = parse_cookie_header(header) ++ with caplog.at_level(logging.DEBUG): ++ result = parse_cookie_header(header) + # Should skip the invalid cookie but continue parsing + assert len(result) == 2 + assert result[0][0] == "good" + assert result[0][1].value == "value" + assert result[1][0] == "another" + assert result[1][1].value == "test" +- assert "Can not load cookie: Illegal cookie name 'invalid,cookie'" in caplog.text ++ assert "Cannot load cookie. Illegal cookie name" in caplog.text ++ assert "'invalid,cookie'" in caplog.text + + + @pytest.mark.parametrize( diff --git a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb index 84dd369753..6dc7acfbd5 100644 --- a/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb +++ b/meta-python/recipes-devtools/python/python3-aiohttp_3.12.15.bb @@ -11,6 +11,7 @@ SRC_URI += "file://CVE-2025-69224.patch \ file://CVE-2025-69228.patch \ file://CVE-2025-69229-1.patch \ file://CVE-2025-69229-2.patch \ + file://CVE-2025-69230.patch \ " SRC_URI[sha256sum] = "4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2"