Files
meta-openembedded/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2026-34525_p1.patch
T
Darsh Kelaiya 73aac78272 python3-aiohttp: fix CVE-2026-34525
This patch applies the reviewed upstream fix commits shown in
[1] and [2]. The advisory identifying the fix is referenced in
[3].

[1] https://github.com/aio-libs/aiohttp/commit/e00ca3cca92c465c7913c4beb763a72da9ed8349
[2] https://github.com/aio-libs/aiohttp/commit/53e2e6fc58b89c6185be7820bd2c9f40216b3000
[3] https://nvd.nist.gov/vuln/detail/CVE-2026-34525

Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
2026-10-26 10:10:35 +05:30

129 lines
4.3 KiB
Diff

From 4032dcab4b75e875cb81e9a8726214c38b66747a Mon Sep 17 00:00:00 2001
From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com>
Date: Sun, 15 Mar 2026 13:58:08 +0000
Subject: [PATCH] [PR #12240/345d2537 backport][3.13] Reject duplicate
singleton headers in C extension parser (#12241)
**This is a backport of PR #12240 as merged into master
(345d25371562dd56de099f1fcd5720e96c6e7702).**
CVE: CVE-2026-34525
Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/e00ca3cca92c465c7913c4beb763a72da9ed8349]
Co-authored-by: Rodrigo Nogueira <rodrigo.b.nogueira@gmail.com>
(cherry picked from commit e00ca3cca92c465c7913c4beb763a72da9ed8349)
Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
---
CHANGES/12240.bugfix.rst | 5 +++++
aiohttp/_http_parser.pyx | 22 +++++++++++++++++++++
tests/test_http_parser.py | 41 +++++++++++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
create mode 100644 CHANGES/12240.bugfix.rst
diff --git a/CHANGES/12240.bugfix.rst b/CHANGES/12240.bugfix.rst
new file mode 100644
index 000000000..49508b3f5
--- /dev/null
+++ b/CHANGES/12240.bugfix.rst
@@ -0,0 +1,5 @@
+Rejected duplicate singleton headers (``Host``, ``Content-Type``,
+``Content-Length``, etc.) in the C extension HTTP parser to match
+the pure Python parser behavior, preventing potential host-based
+access control bypasses via parser differentials
+-- by :user:`rodrigobnogueira`.
diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx
index 213ce2f0c..bb7bf673d 100644
--- a/aiohttp/_http_parser.pyx
+++ b/aiohttp/_http_parser.pyx
@@ -72,6 +72,20 @@ cdef object StreamReader = _StreamReader
cdef object DeflateBuffer = _DeflateBuffer
+# https://www.rfc-editor.org/rfc/rfc9110.html#section-5.5-6
+cdef tuple SINGLETON_HEADERS = (
+ hdrs.CONTENT_LENGTH,
+ hdrs.CONTENT_LOCATION,
+ hdrs.CONTENT_RANGE,
+ hdrs.CONTENT_TYPE,
+ hdrs.ETAG,
+ hdrs.HOST,
+ hdrs.MAX_FORWARDS,
+ hdrs.SERVER,
+ hdrs.TRANSFER_ENCODING,
+ hdrs.USER_AGENT,
+)
+
cdef inline object extend(object buf, const char* at, size_t length):
cdef Py_ssize_t s
cdef char* ptr
@@ -438,6 +452,14 @@ cdef class HttpParser:
raw_headers = tuple(self._raw_headers)
headers = CIMultiDictProxy(self._headers)
+ # https://www.rfc-editor.org/rfc/rfc9110.html#name-collected-abnf
+ bad_hdr = next(
+ (h for h in SINGLETON_HEADERS if len(headers.getall(h, ())) > 1),
+ None,
+ )
+ if bad_hdr is not None:
+ raise BadHttpMessage(f"Duplicate '{bad_hdr}' header found.")
+
if self._cparser.type == cparser.HTTP_REQUEST:
h_upg = headers.get("upgrade", "")
allowed = upgrade and h_upg.isascii() and h_upg.lower() in ALLOWED_UPGRADES
diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py
index be7446e0a..b0a282f3e 100644
--- a/tests/test_http_parser.py
+++ b/tests/test_http_parser.py
@@ -263,6 +263,47 @@ def test_content_length_transfer_encoding(parser: Any) -> None:
parser.feed_data(text)
+@pytest.mark.parametrize(
+ "hdr",
+ (
+ "Content-Length",
+ "Content-Location",
+ "Content-Range",
+ "Content-Type",
+ "ETag",
+ "Host",
+ "Max-Forwards",
+ "Server",
+ "Transfer-Encoding",
+ "User-Agent",
+ ),
+)
+def test_duplicate_singleton_header_rejected(
+ parser: HttpRequestParser, hdr: str
+) -> None:
+ val1, val2 = ("1", "2") if hdr == "Content-Length" else ("value1", "value2")
+ text = (
+ f"GET /test HTTP/1.1\r\n"
+ f"Host: example.com\r\n"
+ f"{hdr}: {val1}\r\n"
+ f"{hdr}: {val2}\r\n"
+ f"\r\n"
+ ).encode()
+ with pytest.raises(http_exceptions.BadHttpMessage, match="Duplicate"):
+ parser.feed_data(text)
+
+
+def test_duplicate_host_header_rejected(parser: HttpRequestParser) -> None:
+ text = (
+ b"GET /admin HTTP/1.1\r\n"
+ b"Host: admin.example\r\n"
+ b"Host: public.example\r\n"
+ b"\r\n"
+ )
+ with pytest.raises(http_exceptions.BadHttpMessage, match="Duplicate.*Host"):
+ parser.feed_data(text)
+
+
def test_bad_chunked_py(loop: Any, protocol: Any) -> None:
"""Test that invalid chunked encoding doesn't allow content-length to be used."""
parser = HttpRequestParserPy(
--
2.35.6