| Message ID | 20260127134721.76918-1-adarsh.jagadish.kamini@est.tech |
|---|---|
| State | New |
| Delegated to: | Yoann Congal |
| Headers | show |
| Series | [scarthgap] python-urllib3: Backport fix CVE-2026-21441 | expand |
Thank you for your submission. Patchtest identified one or more issues with the patch. Please see the log below for more information: --- Testing patch /home/patchtest/share/mboxes/scarthgap-python-urllib3-Backport-fix-CVE-2026-21441.patch FAIL: test mbox format: Series has malformed diff lines. Create the series again using git-format-patch and ensure it applies using git am (test_mbox.TestMbox.test_mbox_format) PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence) PASS: test author valid (test_mbox.TestMbox.test_author_valid) PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence) PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags) PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade) PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format) PASS: test shortlog length (test_mbox.TestMbox.test_shortlog_length) PASS: test target mailing list (test_mbox.TestMbox.test_target_mailing_list) SKIP: pretest pylint: Python-unidiff parse error (test_python_pylint.PyLint.pretest_pylint) SKIP: test CVE tag format: Parse error Hunk diff line expected: diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb SKIP: test Signed-off-by presence: Parse error Hunk diff line expected: diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb SKIP: test Upstream-Status presence: Parse error Hunk diff line expected: diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format) SKIP: test pylint: Python-unidiff parse error (test_python_pylint.PyLint.test_pylint) SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head) --- Please address the issues identified and submit a new revision of the patch, or alternatively, reply to this email with an explanation of why the patch should be accepted. If you believe these results are due to an error in patchtest, please submit a bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category under 'Yocto Project Subprojects'). For more information on specific failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank you!
Le mar. 27 janv. 2026 à 14:47, adarsh.jagadish.kamini via lists.openembedded.org <adarsh.jagadish.kamini= est.tech@lists.openembedded.org> a écrit : > From: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech> > > Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech> > --- > .../python3-urllib3/CVE-2026-21441.patch | 105 ++++++++++++++++++ > .../python/python3-urllib3_2.2.2.bb | 1 + > 2 files changed, 106 insertions(+) > Hello, Thank you for the patch. Since this is the second version of a patch you sent previously, it should have "[PATCH v2]" in the subject (the -v2 option of git-send-email works well). Also, for the next patches, please include a justification as to why you think this patch does fix the CVE. For example, in this case, "Include the patch linked in the NVD report : https://nvd.nist.gov/vuln/detail/CVE-2026-21441" is enough. I will take this patch into testing (with a commit message modification). Regards, create mode 100644 > meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch > > diff --git > a/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch > b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch > new file mode 100644 > index 0000000000..16af67af31 > --- /dev/null > +++ b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch > @@ -0,0 +1,105 @@ > +From 686d2bdd4affd3c86e605f54a72afe53c920f72f Mon Sep 17 00:00:00 2001 > +From: Illia Volochii <illia.volochii@gmail.com> > +Date: Wed, 7 Jan 2026 18:07:30 +0200 > +Subject: [OE-core][scarthgap][PATCH] python-urllib3: Backport fix > CVE-2026-21441 > + > +Bugfixes > +-------- > + > +- Fixed a high-severity security issue where decompression-bomb > safeguards of > + the streaming API were bypassed when HTTP redirects were followed. > + (`GHSA-38jv-5279-wg99 < > https://github.com/urllib3/urllib3/security/advisories/GHSA-38jv-5279-wg99 > >`__) > + > +* Stop decoding response content during redirects needlessly > + > +* Rename the new query parameter > + > +* Add a changelog entry > + > +CVE: CVE-2026-21441 > + > +Upstream-Status: Backport [ > https://github.com/urllib3/urllib3/commit/8864ac407bba8607950025e0979c4c69bc7abc7b > ] > + > +Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech> > +--- > + dummyserver/app.py | 8 +++++++- > + src/urllib3/response.py | 6 +++++- > + test/with_dummyserver/test_connectionpool.py | 19 +++++++++++++++++++ > + 3 files changed, 31 insertions(+), 2 deletions(-) > + > +diff --git a/dummyserver/app.py b/dummyserver/app.py > +index 9fc9d1b7..c4978152 100644 > +--- a/dummyserver/app.py > ++++ b/dummyserver/app.py > +@@ -233,10 +233,16 @@ async def redirect() -> ResponseReturnValue: > + values = await request.values > + target = values.get("target", "/") > + status = values.get("status", "303 See Other") > ++ compressed = values.get("compressed") == "true" > + status_code = status.split(" ")[0] > + > + headers = [("Location", target)] > +- return await make_response("", status_code, headers) > ++ if compressed: > ++ headers.append(("Content-Encoding", "gzip")) > ++ data = gzip.compress(b"foo") > ++ else: > ++ data = b"" > ++ return await make_response(data, status_code, headers) > + > + > + @hypercorn_app.route("/redirect_after") > +diff --git a/src/urllib3/response.py b/src/urllib3/response.py > +index a0273d65..909da62b 100644 > +--- a/src/urllib3/response.py > ++++ b/src/urllib3/response.py > +@@ -646,7 +646,11 @@ class HTTPResponse(BaseHTTPResponse): > + Unread data in the HTTPResponse connection blocks the connection > from being released back to the pool. > + """ > + try: > +- self.read() > ++ self.read( > ++ # Do not spend resources decoding the content unless > ++ # decoding has already been initiated. > ++ decode_content=self._has_decoded_content, > ++ ) > + except (HTTPError, OSError, BaseSSLError, HTTPException): > + pass > + > +diff --git a/test/with_dummyserver/test_connectionpool.py > b/test/with_dummyserver/test_connectionpool.py > +index 4fbe6a4f..ebcdf9bf 100644 > +--- a/test/with_dummyserver/test_connectionpool.py > ++++ b/test/with_dummyserver/test_connectionpool.py > +@@ -480,6 +480,25 @@ class > TestConnectionPool(HypercornDummyServerTestCase): > + assert r.status == 200 > + assert r.data == b"Dummy server!" > + > ++ @mock.patch("urllib3.response.GzipDecoder.decompress") > ++ def test_no_decoding_with_redirect_when_preload_disabled( > ++ self, gzip_decompress: mock.MagicMock > ++ ) -> None: > ++ """ > ++ Test that urllib3 does not attempt to decode a gzipped redirect > ++ response when `preload_content` is set to `False`. > ++ """ > ++ with HTTPConnectionPool(self.host, self.port) as pool: > ++ # Three requests are expected: two redirects and one final / > 200 OK. > ++ response = pool.request( > ++ "GET", > ++ "/redirect", > ++ fields={"target": "/redirect?compressed=true", > "compressed": "true"}, > ++ preload_content=False, > ++ ) > ++ assert response.status == 200 > ++ gzip_decompress.assert_not_called() > ++ > + def test_303_redirect_makes_request_lose_body(self) -> None: > + with HTTPConnectionPool(self.host, self.port) as pool: > + response = pool.request( > +-- > +2.44.0 > + > diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb > b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb > index 620927322a..f6ac8f89ca 100644 > --- a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb > +++ b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb > @@ -11,6 +11,7 @@ SRC_URI += " \ > file://CVE-2025-50181.patch \ > file://CVE-2025-66418.patch \ > file://CVE-2025-66471.patch \ > + file://CVE-2026-21441.patch \ > " > > RDEPENDS:${PN} += "\ > -- > 2.44.0 > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#230043): > https://lists.openembedded.org/g/openembedded-core/message/230043 > Mute This Topic: https://lists.openembedded.org/mt/117488019/4316185 > Group Owner: openembedded-core+owner@lists.openembedded.org > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [ > yoann.congal@smile.fr] > -=-=-=-=-=-=-=-=-=-=-=- > >
diff --git a/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch new file mode 100644 index 0000000000..16af67af31 --- /dev/null +++ b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-21441.patch @@ -0,0 +1,105 @@ +From 686d2bdd4affd3c86e605f54a72afe53c920f72f Mon Sep 17 00:00:00 2001 +From: Illia Volochii <illia.volochii@gmail.com> +Date: Wed, 7 Jan 2026 18:07:30 +0200 +Subject: [OE-core][scarthgap][PATCH] python-urllib3: Backport fix CVE-2026-21441 + +Bugfixes +-------- + +- Fixed a high-severity security issue where decompression-bomb safeguards of + the streaming API were bypassed when HTTP redirects were followed. + (`GHSA-38jv-5279-wg99 <https://github.com/urllib3/urllib3/security/advisories/GHSA-38jv-5279-wg99>`__) + +* Stop decoding response content during redirects needlessly + +* Rename the new query parameter + +* Add a changelog entry + +CVE: CVE-2026-21441 + +Upstream-Status: Backport [https://github.com/urllib3/urllib3/commit/8864ac407bba8607950025e0979c4c69bc7abc7b] + +Signed-off-by: Adarsh Jagadish Kamini <adarsh.jagadish.kamini@est.tech> +--- + dummyserver/app.py | 8 +++++++- + src/urllib3/response.py | 6 +++++- + test/with_dummyserver/test_connectionpool.py | 19 +++++++++++++++++++ + 3 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/dummyserver/app.py b/dummyserver/app.py +index 9fc9d1b7..c4978152 100644 +--- a/dummyserver/app.py ++++ b/dummyserver/app.py +@@ -233,10 +233,16 @@ async def redirect() -> ResponseReturnValue: + values = await request.values + target = values.get("target", "/") + status = values.get("status", "303 See Other") ++ compressed = values.get("compressed") == "true" + status_code = status.split(" ")[0] + + headers = [("Location", target)] +- return await make_response("", status_code, headers) ++ if compressed: ++ headers.append(("Content-Encoding", "gzip")) ++ data = gzip.compress(b"foo") ++ else: ++ data = b"" ++ return await make_response(data, status_code, headers) + + + @hypercorn_app.route("/redirect_after") +diff --git a/src/urllib3/response.py b/src/urllib3/response.py +index a0273d65..909da62b 100644 +--- a/src/urllib3/response.py ++++ b/src/urllib3/response.py +@@ -646,7 +646,11 @@ class HTTPResponse(BaseHTTPResponse): + Unread data in the HTTPResponse connection blocks the connection from being released back to the pool. + """ + try: +- self.read() ++ self.read( ++ # Do not spend resources decoding the content unless ++ # decoding has already been initiated. ++ decode_content=self._has_decoded_content, ++ ) + except (HTTPError, OSError, BaseSSLError, HTTPException): + pass + +diff --git a/test/with_dummyserver/test_connectionpool.py b/test/with_dummyserver/test_connectionpool.py +index 4fbe6a4f..ebcdf9bf 100644 +--- a/test/with_dummyserver/test_connectionpool.py ++++ b/test/with_dummyserver/test_connectionpool.py +@@ -480,6 +480,25 @@ class TestConnectionPool(HypercornDummyServerTestCase): + assert r.status == 200 + assert r.data == b"Dummy server!" + ++ @mock.patch("urllib3.response.GzipDecoder.decompress") ++ def test_no_decoding_with_redirect_when_preload_disabled( ++ self, gzip_decompress: mock.MagicMock ++ ) -> None: ++ """ ++ Test that urllib3 does not attempt to decode a gzipped redirect ++ response when `preload_content` is set to `False`. ++ """ ++ with HTTPConnectionPool(self.host, self.port) as pool: ++ # Three requests are expected: two redirects and one final / 200 OK. ++ response = pool.request( ++ "GET", ++ "/redirect", ++ fields={"target": "/redirect?compressed=true", "compressed": "true"}, ++ preload_content=False, ++ ) ++ assert response.status == 200 ++ gzip_decompress.assert_not_called() ++ + def test_303_redirect_makes_request_lose_body(self) -> None: + with HTTPConnectionPool(self.host, self.port) as pool: + response = pool.request( +-- +2.44.0 + diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb index 620927322a..f6ac8f89ca 100644 --- a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb +++ b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb @@ -11,6 +11,7 @@ SRC_URI += " \