Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python310 for openSUSE:Factory checked in at 2026-04-28 11:58:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python310 (Old) and /work/SRC/openSUSE:Factory/.python310.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python310" Tue Apr 28 11:58:43 2026 rev:77 rq:1349663 version:3.10.20 Changes: -------- --- /work/SRC/openSUSE:Factory/python310/python310.changes 2026-04-19 14:21:22.186108232 +0200 +++ /work/SRC/openSUSE:Factory/.python310.new.11940/python310.changes 2026-04-28 12:02:39.145162129 +0200 @@ -1,0 +2,28 @@ +Mon Apr 27 13:48:41 UTC 2026 - Matej Cepl <[email protected]> + +- Add CVE-2026-6019-Morsel-js_output.patch protects against HTML + injection by Base64-encoding cookie values embedded in JS + (bsc#1262654, CVE-2026-6019, gh#python/cpython#90309). + +------------------------------------------------------------------- +Sat Apr 25 16:42:59 UTC 2026 - Matej Cepl <[email protected]> + +- Add CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch which rejects + CR/LF in HTTP tunnel request headers (bsc#1261969, + CVE-2026-1502, gh#python/cpython#146211). + +------------------------------------------------------------------- +Sat Apr 25 00:14:50 UTC 2026 - Matej Cepl <[email protected]> + +- Add CVE-2026-4786-webbrowser-open-action.patch, which fixes + webbrowser %action substitution bypass of dash-prefix check + (bsc#1262319, CVE-2026-4786, gh#python/cpython#148169). + +------------------------------------------------------------------- +Fri Apr 24 17:15:39 UTC 2026 - Matej Cepl <[email protected]> + +- Add CVE-2026-6100-use-after-free-decompression.patch preventing + dangling pointer which can end in the use-after-free error + (CVE-2026-6100, bsc#1262098, gh#python/cpython#148395). + +------------------------------------------------------------------- New: ---- CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch CVE-2026-4786-webbrowser-open-action.patch CVE-2026-6019-Morsel-js_output.patch CVE-2026-6100-use-after-free-decompression.patch ----------(New B)---------- New: - Add CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch which rejects CR/LF in HTTP tunnel request headers (bsc#1261969, New: - Add CVE-2026-4786-webbrowser-open-action.patch, which fixes webbrowser %action substitution bypass of dash-prefix check New: - Add CVE-2026-6019-Morsel-js_output.patch protects against HTML injection by Base64-encoding cookie values embedded in JS New: - Add CVE-2026-6100-use-after-free-decompression.patch preventing dangling pointer which can end in the use-after-free error ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python310.spec ++++++ --- /var/tmp/diff_new_pack.0JhXXU/_old 2026-04-28 12:02:40.709226921 +0200 +++ /var/tmp/diff_new_pack.0JhXXU/_new 2026-04-28 12:02:40.713227087 +0200 @@ -233,6 +233,18 @@ # PATCH-FIX-UPSTREAM CVE-2026-3446-base64-padding.patch bsc#1261970 [email protected] # Do not ignore excess Base64 data after the first padded quad Patch47: CVE-2026-3446-base64-padding.patch +# PATCH-FIX-UPSTREAM CVE-2026-6100-use-after-free-decompression.patch bsc#1262098 [email protected] +# NULL dangling pointer to avoid use-after-free error +Patch48: CVE-2026-6100-use-after-free-decompression.patch +# PATCH-FIX-UPSTREAM CVE-2026-4786-webbrowser-open-action.patch bsc#1262319 [email protected] +# Fix webbrowser %action substitution bypass of dash-prefix check +Patch49: CVE-2026-4786-webbrowser-open-action.patch +# PATCH-FIX-UPSTREAM CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch bsc#1261969 [email protected] +# Reject CR/LF in HTTP tunnel request headers +Patch50: CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch +# PATCH-FIX-UPSTREAM CVE-2026-6019-Morsel-js_output.patch bsc#1262654 [email protected] +# Base64-encode cookie values embedded in JS +Patch51: CVE-2026-6019-Morsel-js_output.patch ### END OF PATCHES BuildRequires: autoconf-archive BuildRequires: automake ++++++ CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch ++++++ >From fb7005a70754442801e4cb994446aae76c2439a4 Mon Sep 17 00:00:00 2001 From: Seth Larson <[email protected]> Date: Fri, 10 Apr 2026 10:21:42 -0500 Subject: [PATCH] [3.10] gh-146211: Reject CR/LF in HTTP tunnel request headers (GH-146212) (cherry picked from commit 05ed7ce7ae9e17c23a04085b2539fe6d6d3cef69) Co-authored-by: Seth Larson <[email protected]> Co-authored-by: Illia Volochii <[email protected]> --- Lib/http/client.py | 11 ++++- Lib/test/test_httplib.py | 45 +++++++++++++++++++ ...-03-20-09-29-42.gh-issue-146211.PQVbs7.rst | 2 + 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index c8ab5b7662c334..2a8f55f2a47159 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -925,11 +925,20 @@ def set_debuglevel(self, level): self.debuglevel = level def _tunnel(self): + if _contains_disallowed_url_pchar_re.search(self._tunnel_host): + raise ValueError('Tunnel host can\'t contain control characters %r' + % (self._tunnel_host,)) connect = b"CONNECT %s:%d HTTP/1.0\r\n" % ( self._tunnel_host.encode("ascii"), self._tunnel_port) headers = [connect] for header, value in self._tunnel_headers.items(): - headers.append(f"{header}: {value}\r\n".encode("latin-1")) + header_bytes = header.encode("latin-1") + value_bytes = value.encode("latin-1") + if not _is_legal_header_name(header_bytes): + raise ValueError('Invalid header name %r' % (header_bytes,)) + if _is_illegal_header_value(value_bytes): + raise ValueError('Invalid header value %r' % (value_bytes,)) + headers.append(b"%s: %s\r\n" % (header_bytes, value_bytes)) headers.append(b"\r\n") # Making a single send() call instead of one per line encourages # the host OS to use a more optimal packet size instead of diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 89ec5f6f1c5383..3e2ab68e98f1fd 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -351,6 +351,51 @@ def test_invalid_headers(self): with self.assertRaisesRegex(ValueError, 'Invalid header'): conn.putheader(name, value) + def test_invalid_tunnel_headers(self): + cases = ( + ('Invalid\r\nName', 'ValidValue'), + ('Invalid\rName', 'ValidValue'), + ('Invalid\nName', 'ValidValue'), + ('\r\nInvalidName', 'ValidValue'), + ('\rInvalidName', 'ValidValue'), + ('\nInvalidName', 'ValidValue'), + (' InvalidName', 'ValidValue'), + ('\tInvalidName', 'ValidValue'), + ('Invalid:Name', 'ValidValue'), + (':InvalidName', 'ValidValue'), + ('ValidName', 'Invalid\r\nValue'), + ('ValidName', 'Invalid\rValue'), + ('ValidName', 'Invalid\nValue'), + ('ValidName', 'InvalidValue\r\n'), + ('ValidName', 'InvalidValue\r'), + ('ValidName', 'InvalidValue\n'), + ) + for name, value in cases: + with self.subTest((name, value)): + conn = client.HTTPConnection('example.com') + conn.set_tunnel('tunnel', headers={ + name: value + }) + conn.sock = FakeSocket('') + with self.assertRaisesRegex(ValueError, 'Invalid header'): + conn._tunnel() # Called in .connect() + + def test_invalid_tunnel_host(self): + cases = ( + 'invalid\r.host', + '\ninvalid.host', + 'invalid.host\r\n', + 'invalid.host\x00', + 'invalid host', + ) + for tunnel_host in cases: + with self.subTest(tunnel_host): + conn = client.HTTPConnection('example.com') + conn.set_tunnel(tunnel_host) + conn.sock = FakeSocket('') + with self.assertRaisesRegex(ValueError, 'Tunnel host can\'t contain control characters'): + conn._tunnel() # Called in .connect() + def test_headers_debuglevel(self): body = ( b'HTTP/1.1 200 OK\r\n' diff --git a/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst new file mode 100644 index 00000000000000..4993633b8ebebb --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst @@ -0,0 +1,2 @@ +Reject CR/LF characters in tunnel request headers for the +HTTPConnection.set_tunnel() method. ++++++ CVE-2026-4786-webbrowser-open-action.patch ++++++ >From 881ff02c42844904233bc7b29b571fa72cb9ce97 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <[email protected]> Date: Mon, 13 Apr 2026 20:02:52 +0100 Subject: [PATCH] [3.10] gh-148169: Fix webbrowser `%action` substitution bypass of dash-prefix check (GH-148170) (cherry picked from commit d22922c8a7958353689dc4763dd72da2dea03fff) Co-authored-by: Stan Ulbrych <[email protected]> --- Lib/test/test_webbrowser.py | 8 ++++++++ Lib/webbrowser.py | 5 +++-- Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst Index: Python-3.10.20/Lib/test/test_webbrowser.py =================================================================== --- Python-3.10.20.orig/Lib/test/test_webbrowser.py 2026-04-25 19:08:23.732635863 +0200 +++ Python-3.10.20/Lib/test/test_webbrowser.py 2026-04-25 19:08:23.790109662 +0200 @@ -97,6 +97,14 @@ options=[], arguments=[URL]) + def test_reject_action_dash_prefixes(self): + browser = self.browser_class(name=CMD_NAME) + with self.assertRaises(ValueError): + browser.open('%action--incognito') + # new=1: action is "--new-window", so "%action" itself expands to + # a dash-prefixed flag even with no dash in the original URL. + with self.assertRaises(ValueError): + browser.open('%action', new=1) class MozillaCommandTest(CommandTestMixin, unittest.TestCase): Index: Python-3.10.20/Lib/webbrowser.py =================================================================== --- Python-3.10.20.orig/Lib/webbrowser.py 2026-04-25 19:08:23.733048200 +0200 +++ Python-3.10.20/Lib/webbrowser.py 2026-04-25 19:08:23.790594185 +0200 @@ -263,7 +263,6 @@ def open(self, url, new=0, autoraise=True): sys.audit("webbrowser.open", url) - self._check_url(url) if new == 0: action = self.remote_action elif new == 1: @@ -277,7 +276,9 @@ raise Error("Bad 'new' parameter to open(); " + "expected 0, 1, or 2, got %s" % new) - args = [arg.replace("%s", url).replace("%action", action) + self._check_url(url.replace("%action", action)) + + args = [arg.replace("%action", action).replace("%s", url) for arg in self.remote_args] args = [arg for arg in args if arg] success = self._invoke(args, True, autoraise, url) Index: Python-3.10.20/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.10.20/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst 2026-04-25 19:08:23.790831983 +0200 @@ -0,0 +1,2 @@ +A bypass in :mod:`webbrowser` allowed URLs prefixed with ``%action`` to pass +the dash-prefix safety check. ++++++ CVE-2026-6019-Morsel-js_output.patch ++++++ >From a67e6c856353c04782f38bca6d6c1c3d3287c653 Mon Sep 17 00:00:00 2001 From: Seth Larson <[email protected]> Date: Wed, 22 Apr 2026 14:22:31 -0500 Subject: [PATCH] gh-90309: Base64-encode cookie values embedded in JS (cherry picked from commit 76b3923d688c0efc580658476c5f525ec8735104) Co-authored-by: Seth Larson <[email protected]> --- Lib/http/cookies.py | 8 ++ Lib/test/test_http_cookies.py | 29 ++++++---- Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst | 3 + 3 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst Index: Python-3.10.20/Lib/http/cookies.py =================================================================== --- Python-3.10.20.orig/Lib/http/cookies.py 2026-04-27 18:47:10.197962881 +0200 +++ Python-3.10.20/Lib/http/cookies.py 2026-04-27 18:47:10.312428247 +0200 @@ -389,17 +389,21 @@ return '<%s: %s>' % (self.__class__.__name__, self.OutputString()) def js_output(self, attrs=None): + import base64 # Print javascript output_string = self.OutputString(attrs) if _has_control_character(output_string): raise CookieError("Control characters are not allowed in cookies") + # Base64-encode value to avoid template + # injection in cookie values. + output_encoded = base64.b64encode(output_string.encode('utf-8')).decode("ascii") return """ <script type="text/javascript"> <!-- begin hiding - document.cookie = \"%s\"; + document.cookie = atob(\"%s\"); // end hiding --> </script> - """ % (output_string.replace('"', r'\"')) + """ % (output_encoded,) def OutputString(self, attrs=None): # Build up our result Index: Python-3.10.20/Lib/test/test_http_cookies.py =================================================================== --- Python-3.10.20.orig/Lib/test/test_http_cookies.py 2026-04-27 18:47:10.198375768 +0200 +++ Python-3.10.20/Lib/test/test_http_cookies.py 2026-04-27 18:47:10.312666355 +0200 @@ -1,5 +1,5 @@ # Simple test suite for http/cookies.py - +import base64 import copy from test.support import run_unittest, run_doctest import unittest @@ -106,17 +106,19 @@ self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" <script type="text/javascript"> <!-- begin hiding - document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1"; + document.cookie = atob("{cookie_encoded}"); // end hiding --> </script> """) - self.assertEqual(C.js_output(['path']), r""" + cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" <script type="text/javascript"> <!-- begin hiding - document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme"; + document.cookie = atob("{cookie_encoded}"); // end hiding --> </script> """) @@ -213,17 +215,19 @@ self.assertEqual(C.output(['path']), 'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme') - self.assertEqual(C.js_output(), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii') + self.assertEqual(C.js_output(), fr""" <script type="text/javascript"> <!-- begin hiding - document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1"; + document.cookie = atob("{expected_encoded_cookie}"); // end hiding --> </script> """) - self.assertEqual(C.js_output(['path']), r""" + expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii') + self.assertEqual(C.js_output(['path']), fr""" <script type="text/javascript"> <!-- begin hiding - document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme"; + document.cookie = atob("{expected_encoded_cookie}"); // end hiding --> </script> """) @@ -314,13 +318,16 @@ self.assertEqual( M.output(), "Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i)) + expected_encoded_cookie = base64.b64encode( + ("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii") + ).decode('ascii') expected_js_output = """ <script type="text/javascript"> <!-- begin hiding - document.cookie = "%s=%s; Path=/foo"; + document.cookie = atob("%s"); // end hiding --> </script> - """ % (i, "%s_coded_val" % i) + """ % (expected_encoded_cookie,) self.assertEqual(M.js_output(), expected_js_output) for i in ["foo bar", "foo@bar"]: # Try some illegal characters Index: Python-3.10.20/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.10.20/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst 2026-04-27 18:47:10.313120060 +0200 @@ -0,0 +1,3 @@ +Base64-encode values when embedding cookies to JavaScript using the +:meth:`http.cookies.BaseCookie.js_output` method to avoid injection +and escaping. ++++++ CVE-2026-6100-use-after-free-decompression.patch ++++++ >From fe18959c5d6bdb1bb504f46bf09bad302314fe87 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <[email protected]> Date: Mon, 13 Apr 2026 02:14:54 +0100 Subject: [PATCH 1/2] gh-148395: Fix a possible UAF in `{LZMA,BZ2,_Zlib}Decompressor` (GH-148396) Fix dangling input pointer after `MemoryError` in _lzma/_bz2/_ZlibDecompressor.decompress (cherry picked from commit 8fc66aef6d7b3ae58f43f5c66f9366cc8cbbfcd2) --- Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst | 5 +++++ Modules/_bz2module.c | 1 + Modules/_lzmamodule.c | 1 + 3 files changed, 7 insertions(+) create mode 100644 Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst Index: Python-3.10.20/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.10.20/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst 2026-04-24 23:07:18.740388372 +0200 @@ -0,0 +1,5 @@ +Fix a dangling input pointer in :class:`lzma.LZMADecompressor`, +:class:`bz2.BZ2Decompressor` +when memory allocation fails with :exc:`MemoryError`, which could let a +subsequent :meth:`!decompress` call read or write through a stale pointer to +the already-released caller buffer. Index: Python-3.10.20/Modules/_bz2module.c =================================================================== --- Python-3.10.20.orig/Modules/_bz2module.c 2026-03-03 01:49:35.000000000 +0100 +++ Python-3.10.20/Modules/_bz2module.c 2026-04-24 23:07:18.739985292 +0200 @@ -595,6 +595,7 @@ return result; error: + bzs->next_in = NULL; Py_XDECREF(result); return NULL; } Index: Python-3.10.20/Modules/_lzmamodule.c =================================================================== --- Python-3.10.20.orig/Modules/_lzmamodule.c 2026-03-03 01:49:35.000000000 +0100 +++ Python-3.10.20/Modules/_lzmamodule.c 2026-04-24 23:07:18.740190569 +0200 @@ -1102,6 +1102,7 @@ return result; error: + lzs->next_in = NULL; Py_XDECREF(result); return NULL; } ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.0JhXXU/_old 2026-04-28 12:02:41.029240178 +0200 +++ /var/tmp/diff_new_pack.0JhXXU/_new 2026-04-28 12:02:41.033240344 +0200 @@ -1,6 +1,6 @@ -mtime: 1776458219 -commit: cf8e710a886c417bb4b2c136e2a8fc01cac6f38e333eca36fc60ab1547011bba -url: https://src.opensuse.org/python-interpreters/python310.git -revision: cf8e710a886c417bb4b2c136e2a8fc01cac6f38e333eca36fc60ab1547011bba +mtime: 1777308455 +commit: 5bc50c307741eeac7952a643299f31439ef2a3409a0c17a4ba7aa80ba65df8be +url: https://src.opensuse.org/python-interpreters/python310 +revision: 5bc50c307741eeac7952a643299f31439ef2a3409a0c17a4ba7aa80ba65df8be projectscmsync: https://src.opensuse.org/python-interpreters/_ObsPrj ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-04-27 18:47:35.000000000 +0200 @@ -0,0 +1,7 @@ +.osc +*.obscpio +*.osc +_build.* +.pbuild +*.rej +python310-*-build/
