Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python311 for openSUSE:Factory 
checked in at 2026-06-19 16:31:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python311 (Old)
 and      /work/SRC/openSUSE:Factory/.python311.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python311"

Fri Jun 19 16:31:07 2026 rev:69 rq:1357976 version:3.11.15

Changes:
--------
--- /work/SRC/openSUSE:Factory/python311/python311.changes      2026-04-15 
16:03:11.951616173 +0200
+++ /work/SRC/openSUSE:Factory/.python311.new.1956/python311.changes    
2026-06-19 17:22:07.987636642 +0200
@@ -1,0 +2,59 @@
+Sat Jun  6 00:00:00 UTC 2026 - Matej Cepl <[email protected]>
+
+- Keep unversioned Python 3 development entry points in
+  python3-devel: python313-devel no longer provides python3-devel
+  and no longer owns libpython3.so, python3-config, python3.pc,
+  or python3-embed.pc. Do not package versioned GIL pkg-config
+  files in nogil-devel. Also, fix regular expressions in
+  rpmlintrc.
+
+-------------------------------------------------------------------
+Fri May  1 16:05:16 UTC 2026 - Matej Cepl <[email protected]>
+
+- Remove macros.python3.
+
+-------------------------------------------------------------------
+Mon Apr 27 13:48:41 UTC 2026 - Matej Cepl <[email protected]>
+
+- CVE-2026-6019: protect against HTML injection by
+  Base64-encoding cookie values embedded in JS (bsc#1262654,
+  gh#python/cpython#90309)
+  CVE-2026-6019-Morsel-js_output.patch
+
+-------------------------------------------------------------------
+Sat Apr 25 16:42:59 UTC 2026 - Matej Cepl <[email protected]>
+
+- CVE-2026-1502: reject CR/LF in HTTP tunnel request headers
+  (bsc#1261969, gh#python/cpython#146211)
+  CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch
+
+-------------------------------------------------------------------
+Sat Apr 25 00:14:50 UTC 2026 - Matej Cepl <[email protected]>
+
+- CVE-2026-4786: fix webbrowser %action substitution bypass of
+  dash-prefix check (bsc#1262319, gh#python/cpython#148169)
+  CVE-2026-4786-webbrowser-open-action.patch
+
+-------------------------------------------------------------------
+Fri Apr 24 17:15:39 UTC 2026 - Matej Cepl <[email protected]>
+
+- CVE-2026-6100: prevent dangling pointer, which can end in the
+  use-after-free error (bsc#1262098, gh#python/cpython#148395)
+  CVE-2026-6100-use-after-free-decompression.patch
+
+-------------------------------------------------------------------
+Wed Apr 15 18:00:50 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add CVE-2026-3446-base64-padding.patch preventing ignoring
+  excess Base64 data after the first padded quad (bsc#1261970,
+  CVE-2026-3446, gh#python/cpython#145264).
+
+-------------------------------------------------------------------
+Wed Apr  8 16:12:36 CEST 2026 - Matej Cepl <[email protected]>
+
+- Rewrite structure of Python interpreter packages.
+  `python3*` symbols should be now provided by real python3
+  packages and its subpackages instead of the virtual provides
+  (bsc#1258364).
+
+-------------------------------------------------------------------
@@ -3235,5 +3293,0 @@
-
--------------------------------------------------------------------
-Tue Jan 25 16:09:25 UTC 2022 - Matej Cepl <[email protected]>
-
-- Remove second superfluous BR rpm-build-python
@@ -4707 +4761 @@
-------------------------------------------------------------------
+-------------------------------------------------------------------
@@ -5066 +5120 @@
-------------------------------------------------------------------
+-------------------------------------------------------------------
@@ -5917 +5970,0 @@
-

Old:
----
  macros.python3

New:
----
  CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch
  CVE-2026-3446-base64-padding.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:  (bsc#1261969, gh#python/cpython#146211)
  CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch
  New:
- Add CVE-2026-3446-base64-padding.patch preventing ignoring
  excess Base64 data after the first padded quad (bsc#1261970,
  New:  dash-prefix check (bsc#1262319, gh#python/cpython#148169)
  CVE-2026-4786-webbrowser-open-action.patch
  New:  gh#python/cpython#90309)
  CVE-2026-6019-Morsel-js_output.patch
  New:  use-after-free error (bsc#1262098, gh#python/cpython#148395)
  CVE-2026-6100-use-after-free-decompression.patch
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python311.spec ++++++
--- /var/tmp/diff_new_pack.1IDvUO/_old  2026-06-19 17:22:09.427686167 +0200
+++ /var/tmp/diff_new_pack.1IDvUO/_new  2026-06-19 17:22:09.431686305 +0200
@@ -117,7 +117,6 @@
 Source2:        baselibs.conf
 Source3:        README.SUSE
 Source4:        externally_managed.in
-Source7:        macros.python3
 Source8:        import_failed.py
 Source9:        import_failed.map
 Source10:       pre_checkin.sh
@@ -215,6 +214,21 @@
 # PATCH-FIX-UPSTREAM CVE-2026-3479-pkgutil_get_data.patch bsc#1259989 
[email protected]
 # pkgutil.get_data() reject invalid resource arguments
 Patch42:        CVE-2026-3479-pkgutil_get_data.patch
+# PATCH-FIX-UPSTREAM CVE-2026-3446-base64-padding.patch bsc#1261970 
[email protected]
+# Do not ignore excess Base64 data after the first padded quad
+Patch43:        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
+Patch44:        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
+Patch45:        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
+Patch46:        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
+Patch47:        CVE-2026-6019-Morsel-js_output.patch
 ### END OF PATCHES
 BuildRequires:  autoconf-archive
 BuildRequires:  automake
@@ -232,8 +246,9 @@
 BuildRequires:  pkgconfig(uuid)
 BuildRequires:  pkgconfig(zlib)
 #!BuildIgnore:  gdk-pixbuf-loader-rsvg
-%if 0%{?suse_version} >= 1550
-# The provider for python(abi) is in rpm-build-python
+%if 0%{?suse_version} >= 1550 && %{without base}
+# Skip for the base flavor: rpm-build-python requires python3-base, which
+# creates an unresolvable dependency loop when building python3xx-base itself.
 BuildRequires:  rpm-build-python
 %endif
 %if 0%{?suse_version} >= 1500 && 0%{?suse_version} < 1599
@@ -265,11 +280,6 @@
 Recommends:     %{python_pkg_name}-curses
 Recommends:     %{python_pkg_name}-dbm
 Recommends:     %{python_pkg_name}-pip
-%if %{primary_interpreter}
-Provides:       python3 = %{python_version}
-Provides:       python3-readline
-Provides:       python3-sqlite3
-%endif
 %endif
 %{?suse_build_hwcaps_libs}
 
@@ -290,9 +300,6 @@
 %package -n %{python_pkg_name}-tk
 Summary:        TkInter, a Python Tk Interface
 Requires:       %{python_pkg_name} = %{version}
-%if %{primary_interpreter}
-Provides:       python3-tk = %{version}
-%endif
 
 %description -n %{python_pkg_name}-tk
 Python interface to Tk. Tk is the GUI toolkit that comes with Tcl.
@@ -300,9 +307,6 @@
 %package -n %{python_pkg_name}-curses
 Summary:        Python Interface to the (N)Curses Library
 Requires:       %{python_pkg_name} = %{version}
-%if %{primary_interpreter}
-Provides:       python3-curses
-%endif
 
 %description -n %{python_pkg_name}-curses
 An easy to use interface to the (n)curses CUI library. CUI stands for
@@ -311,9 +315,6 @@
 %package -n %{python_pkg_name}-dbm
 Summary:        Python Interface to the GDBM Library
 Requires:       %{python_pkg_name} = %{version}
-%if %{primary_interpreter}
-Provides:       python3-dbm
-%endif
 
 %description -n %{python_pkg_name}-dbm
 An easy to use interface for Unix DBM databases, and more specifically,
@@ -323,9 +324,6 @@
 Summary:        An Integrated Development Environment for Python
 Requires:       %{python_pkg_name} = %{version}
 Requires:       %{python_pkg_name}-tk
-%if %{primary_interpreter}
-Provides:       python3-idle = %{version}
-%endif
 
 %description -n %{python_pkg_name}-idle
 IDLE is a Tkinter based integrated development environment for Python.
@@ -336,9 +334,6 @@
 %package -n %{python_pkg_name}-doc
 Summary:        Package Documentation for Python 3
 Enhances:       %{python_pkg_name} = %{python_version}
-%if %{primary_interpreter}
-Provides:       python3-doc = %{version}
-%endif
 
 %description -n %{python_pkg_name}-doc
 Tutorial, Global Module Index, Language Reference, Library Reference,
@@ -347,9 +342,6 @@
 
 %package -n %{python_pkg_name}-doc-devhelp
 Summary:        Additional Package Documentation for Python 3 in devhelp format
-%if %{primary_interpreter}
-Provides:       python3-doc-devhelp = %{version}
-%endif
 
 %description -n %{python_pkg_name}-doc-devhelp
 Tutorial, Global Module Index, Language Reference, Library Reference,
@@ -371,16 +363,10 @@
 Provides:       %{python_pkg_name}-typing = %{version}
 # python3-xml was merged into python3, now moved into -base
 Provides:       %{python_pkg_name}-xml = %{version}
-%if %{primary_interpreter}
-Provides:       python3-asyncio = %{version}
-Obsoletes:      python3-asyncio < %{version}
-Provides:       python3-base = %{version}
-Obsoletes:      python3-base < %{version}
-Provides:       python3-typing = %{version}
-Obsoletes:      python3-typing < %{version}
-Provides:       python3-xml = %{version}
-Obsoletes:      python3-xml < %{version}
-%endif
+# Explicitly provided because rpm-build-python (which auto-generates this)
+# cannot be installed in the base flavor build root due to a bootstrap cycle:
+# rpm-build-python -> python3-base -> (this package)
+Provides:       python(abi) = %{python_version}
 
 %description -n %{python_pkg_name}-base
 Python is an interpreted, object-oriented programming language, and is
@@ -398,13 +384,6 @@
 Requires:       %{python_pkg_name}-base = %{version}
 Provides:       %{python_pkg_name}-2to3 = %{version}
 Provides:       %{python_pkg_name}-demo = %{version}
-%if %{primary_interpreter}
-Provides:       python3-2to3 = %{version}
-Provides:       python3-demo = %{version}
-Provides:       python3-tools = %{version}
-Obsoletes:      python3-2to3 < %{version}
-Obsoletes:      python3-demo < %{version}
-%endif
 
 %description -n %{python_pkg_name}-tools
 A number of scripts that are useful for building, testing or extending Python,
@@ -413,9 +392,6 @@
 %package -n %{python_pkg_name}-devel
 Summary:        Include Files and Libraries Mandatory for Building Python 
Modules
 Requires:       %{python_pkg_name}-base = %{version}
-%if %{primary_interpreter}
-Provides:       python3-devel = %{version}
-%endif
 
 %description -n %{python_pkg_name}-devel
 The Python programming language's interpreter can be extended with
@@ -432,9 +408,6 @@
 Summary:        Unit tests for Python and its standard library
 Requires:       %{python_pkg_name} = %{version}
 Requires:       %{python_pkg_name}-tk = %{version}
-%if %{primary_interpreter}
-Provides:       python3-testsuite = %{version}
-%endif
 
 %description -n %{python_pkg_name}-testsuite
 Unit tests that are useful for verifying integrity and functionality
@@ -731,20 +704,12 @@
 done
 rm -fv %{buildroot}%{dynlib nis}
 
-# overwrite the copied binary with a link
-ln -sf python%{python_version} %{buildroot}%{_bindir}/python3
-
-# decide to ship python3 or just python3.X
-%if !%{primary_interpreter}
-# base
 rm %{buildroot}%{_bindir}/python3
 rm %{buildroot}%{_bindir}/pydoc3
 rm %{buildroot}%{_mandir}/man1/python3.1
-# devel
 rm %{buildroot}%{_bindir}/python3-config
 rm %{buildroot}%{_libdir}/libpython3.so
 rm %{buildroot}%{_libdir}/pkgconfig/{python3,python3-embed}.pc
-%endif
 
 %if %{with externally_managed}
 # PEP-0668 mark this as a distro maintained python
@@ -782,7 +747,13 @@
 find "$PDOCS" -name "*.bat" -delete
 
 # put gdb helper script into place
-install -m 755 -D Tools/gdb/libpython.py 
%{buildroot}%{_datadir}/gdb/auto-load/%{_libdir}/libpython%{python_abi}.so.%{so_major}.%{so_minor}-gdb.py
+%define gdb_help_script 
libpython%{python_abi}.so.%{so_major}.%{so_minor}-gdb.py
+install -m 755 -D Tools/gdb/libpython.py \
+    %{buildroot}%{_datadir}/gdb/auto-load/%{_libdir}/%{gdb_help_script}
+# don't use %python311_fix_shebang_path to avoid circular dependency via
+# python-rpm-macros
+sed -i "1s@#\!.*python[^ ]*@#\!%{_bindir}/python%{python_version}@" \
+    %{buildroot}%{_datadir}/gdb/auto-load/%{_libdir}/%{gdb_help_script}
 
 # install devel files to /config
 #cp Makefile Makefile.pre.in Makefile.pre 
$RPM_BUILD_ROOT%%{sitedir}/config-%%{python_abi}/
@@ -790,12 +761,6 @@
 # Remove -IVendor/ from python-config boo#1231795
 sed -i 's/-IVendor\///' %{buildroot}%{_bindir}/python%{python_abi}-config
 
-# RPM macros
-%if %{primary_interpreter}
-mkdir -p %{buildroot}%{_rpmconfigdir}/macros.d/
-install -m 644 %{SOURCE7} %{buildroot}%{_rpmconfigdir}/macros.d/ # 
macros.python3
-%endif
-
 # import_failed hooks
 FAILDIR=%{buildroot}/%{sitedir}/_import_failed
 mkdir $FAILDIR
@@ -899,16 +864,11 @@
 
 %files -n %{python_pkg_name}-devel
 %{_libdir}/libpython%{python_abi}.so
-%if %{primary_interpreter}
-%{_libdir}/libpython3.so
-%endif
-%{_libdir}/pkgconfig/*
+%{_libdir}/pkgconfig/python-%{python_version}.pc
+%{_libdir}/pkgconfig/python-%{python_version}-embed.pc
 %{_includedir}/python%{python_abi}
 %{sitedir}/config-%{python_abi}-*
 %{_bindir}/python%{python_abi}-config
-%if %{primary_interpreter}
-%{_bindir}/python3-config
-%endif
 # Own these directories to not depend on gdb
 %dir %{_datadir}/gdb
 %dir %{_datadir}/gdb/auto-load
@@ -938,9 +898,6 @@
 %doc %{_docdir}/%{name}/README.rst
 %license LICENSE
 %doc %{_docdir}/%{name}/README.SUSE
-%if %{primary_interpreter}
-%{_mandir}/man1/python3.1%{?ext_man}
-%endif
 %{_mandir}/man1/python%{python_version}.1%{?ext_man}
 %if %{with externally_managed}
 # PEP-0668
@@ -948,10 +905,6 @@
 %endif
 # license text, not a doc because the code can use it at run-time
 %{sitedir}/LICENSE.txt
-# RPM macros
-%if %{primary_interpreter}
-%{_rpmconfigdir}/macros.d/macros.python3
-%endif
 # binary parts
 %dir %{sitedir}/lib-dynload
 %{dynlib array}
@@ -1057,11 +1010,6 @@
 # import-failed hooks
 %{sitedir}/_import_failed
 %{sitedir}/site-packages/zzzz-import-failed-hooks.pth
-# symlinks
-%if %{primary_interpreter}
-%{_bindir}/python3
-%{_bindir}/pydoc3
-%endif
 # executables
 %attr(755, root, root) %{_bindir}/pydoc%{python_version}
 # %%attr(755, root, root) %%{_bindir}/python%%{python_abi}

++++++ CVE-2026-1502-reject-CRLF-HTTP-tunnel.patch ++++++
>From 043198392795df90c5ceddc8d1337448fd8bef6c Mon Sep 17 00:00:00 2001
From: Seth Larson <[email protected]>
Date: Fri, 10 Apr 2026 10:21:42 -0500
Subject: [PATCH] [3.11] 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 ++++++++++
 Misc/NEWS.d/next/Security/2026-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

Index: Python-3.11.15/Lib/http/client.py
===================================================================
--- Python-3.11.15.orig/Lib/http/client.py      2026-04-25 19:06:55.324666120 
+0200
+++ Python-3.11.15/Lib/http/client.py   2026-04-25 19:07:00.931284454 +0200
@@ -941,12 +941,21 @@
         return ip
 
     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._wrap_ipv6(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
Index: Python-3.11.15/Lib/test/test_httplib.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_httplib.py        2026-04-25 
19:06:57.028324552 +0200
+++ Python-3.11.15/Lib/test/test_httplib.py     2026-04-25 19:07:00.932868704 
+0200
@@ -371,6 +371,51 @@
                 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'
Index: 
Python-3.11.15/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.11.15/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst
     2026-04-25 19:07:00.933147420 +0200
@@ -0,0 +1,2 @@
+Reject CR/LF characters in tunnel request headers for the
+HTTPConnection.set_tunnel() method.

++++++ CVE-2026-3446-base64-padding.patch ++++++
>From bd4ab523ba664863d40470cc718c566158adfa31 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <[email protected]>
Date: Tue, 24 Mar 2026 01:20:26 +0200
Subject: [PATCH] [3.14] gh-145264: Do not ignore excess Base64 data after the
 first padded quad (GH-145267) (GH-146326)

Base64 decoder (see binascii.a2b_base64(), base64.b64decode(), etc)
no longer ignores excess data after the first padded quad in non-strict
(default) mode.  Instead, in conformance with RFC 4648, it ignores the
pad character, "=", if it is present before the end of the encoded data.
(cherry picked from commit 4561f6418a691b3e89aef0901f53fe0dfb7f7c0e)
(cherry picked from commit e31c55121620189a0d1a07b689762d8ca9c1b7fa)

Co-authored-by: Serhiy Storchaka <[email protected]>
---
 Lib/test/test_binascii.py                                               |   33 
+++
 Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst |    4 
 Modules/binascii.c                                                      |   90 
+++++-----
 3 files changed, 78 insertions(+), 49 deletions(-)
 create mode 100644 
Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst

Index: Python-3.11.15/Lib/test/test_binascii.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_binascii.py       2026-04-16 
01:25:00.019387400 +0200
+++ Python-3.11.15/Lib/test/test_binascii.py    2026-04-16 01:37:02.691981027 
+0200
@@ -132,13 +132,20 @@
         def assertDiscontinuousPadding(data, non_strict_mode_expected_result: 
bytes):
             _assertRegexTemplate(r'(?i)Discontinuous padding', data, 
non_strict_mode_expected_result)
 
+        def assertExcessPadding(data, non_strict_mode_expected_result: bytes):
+            _assertRegexTemplate(r'(?i)Excess padding', data, 
non_strict_mode_expected_result)
+
         # Test excess data exceptions
-        assertExcessData(b'ab==a', b'i')
-        assertExcessData(b'ab===', b'i')
-        assertExcessData(b'ab==:', b'i')
-        assertExcessData(b'abc=a', b'i\xb7')
-        assertExcessData(b'abc=:', b'i\xb7')
-        assertExcessData(b'ab==\n', b'i')
+        assertExcessPadding(b'ab===', b'i')
+        assertExcessPadding(b'ab====', b'i')
+        assertNonBase64Data(b'ab==:', b'i')
+        assertExcessData(b'abc=a', b'i\xb7\x1a')
+        assertNonBase64Data(b'abc=:', b'i\xb7')
+        assertNonBase64Data(b'ab==\n', b'i')
+        assertExcessPadding(b'abc==', b'i\xb7')
+        assertExcessPadding(b'abc===', b'i\xb7')
+        assertExcessPadding(b'abc====', b'i\xb7')
+        assertExcessPadding(b'abc=====', b'i\xb7')
 
         # Test non-base64 data exceptions
         assertNonBase64Data(b'\nab==', b'i')
@@ -153,6 +160,20 @@
         assertDiscontinuousPadding(b'ab=c=', b'i\xb7')
         assertDiscontinuousPadding(b'ab=ab==', b'i\xb6\x9b')
 
+    def test_base64_excess_data(self):
+        # Test excess data exceptions
+        def assertExcessData(data, expected):
+            assert_regex = r'(?i)Excess data'
+            data = self.type2test(data)
+            with self.assertRaisesRegex(binascii.Error, assert_regex):
+                binascii.a2b_base64(data, strict_mode=True)
+            self.assertEqual(binascii.a2b_base64(data, strict_mode=False),
+                             expected)
+            self.assertEqual(binascii.a2b_base64(data), expected)
+
+        assertExcessData(b'ab==c=', b'i\xb7')
+        assertExcessData(b'ab==cd', b'i\xb7\x1d')
+        assertExcessData(b'abc=d', b'i\xb7\x1d')
 
     def test_base64errors(self):
         # Test base64 with invalid padding
Index: 
Python-3.11.15/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.11.15/Misc/NEWS.d/next/Library/2026-02-26-20-13-16.gh-issue-145264.4pggX_.rst
      2026-04-16 01:25:07.716277511 +0200
@@ -0,0 +1,4 @@
+Base64 decoder (see :func:`binascii.a2b_base64`, :func:`base64.b64decode`, 
etc) no
+longer ignores excess data after the first padded quad in non-strict
+(default) mode.  Instead, in conformance with :rfc:`4648`, section 3.3, it now 
ignores
+the pad character, "=", if it is present before the end of the encoded data.
Index: Python-3.11.15/Modules/binascii.c
===================================================================
--- Python-3.11.15.orig/Modules/binascii.c      2026-03-03 01:52:57.000000000 
+0100
+++ Python-3.11.15/Modules/binascii.c   2026-04-16 01:33:46.756241326 +0200
@@ -393,7 +393,6 @@
     const unsigned char *ascii_data = data->buf;
     size_t ascii_len = data->len;
     binascii_state *state = NULL;
-    char padding_started = 0;
 
     /* Allocate the buffer */
     Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later 
*/
@@ -404,14 +403,6 @@
         return NULL;
     unsigned char *bin_data_start = bin_data;
 
-    if (strict_mode && ascii_len > 0 && ascii_data[0] == '=') {
-        state = get_binascii_state(module);
-        if (state) {
-            PyErr_SetString(state->Error, "Leading padding not allowed");
-        }
-        goto error_end;
-    }
-
     int quad_pos = 0;
     unsigned char leftchar = 0;
     int pads = 0;
@@ -422,28 +413,34 @@
         ** the invalid ones.
         */
         if (this_ch == BASE64_PAD) {
-            padding_started = 1;
-
-            if (quad_pos >= 2 && quad_pos + ++pads >= 4) {
-                /* A pad sequence means we should not parse more input.
-                ** We've already interpreted the data from the quad at this 
point.
-                ** in strict mode, an error should raise if there's excess 
data after the padding.
-                */
-                if (strict_mode && i + 1 < ascii_len) {
-                    state = get_binascii_state(module);
-                    if (state) {
-                        PyErr_SetString(state->Error, "Excess data after 
padding");
-                    }
-                    goto error_end;
-                }
-
-                goto done;
+            pads++;
+            if (quad_pos >= 2 && quad_pos + pads <= 4) {
+                continue;
             }
-            continue;
+            // See RFC 4648, section-3.3: "specifications MAY ignore the
+            // pad character, "=", treating it as non-alphabet data, if
+            // it is present before the end of the encoded data" and
+            // "the excess pad characters MAY also be ignored."
+            if (!strict_mode) {
+                continue;
+            }
+            if (quad_pos == 1) {
+                /* Set an error below. */
+                break;
+            }
+            state = get_binascii_state(module);
+            if (state) {
+                PyErr_SetString(state->Error,
+                                (quad_pos == 0 && i == 0)
+                                ? "Leading padding not allowed"
+                                : "Excess padding not allowed");
+            }
+            goto error_end;
         }
 
         this_ch = table_a2b_base64[this_ch];
         if (this_ch >= 64) {
+            // See RFC 4648, section-3.3.
             if (strict_mode) {
                 state = get_binascii_state(module);
                 if (state) {
@@ -454,11 +451,14 @@
             continue;
         }
 
-        // Characters that are not '=', in the middle of the padding, are not 
allowed
-        if (strict_mode && padding_started) {
+        // Characters that are not '=', in the middle of the padding, are
+        // not allowed (except when they are). See RFC 4648, section-3.3.
+        if (pads && strict_mode) {
             state = get_binascii_state(module);
             if (state) {
-                PyErr_SetString(state->Error, "Discontinuous padding not 
allowed");
+                PyErr_SetString(state->Error, (quad_pos + pads == 4)
+                    ? "Excess data after padding"
+                    : "Discontinuous padding not allowed");
             }
             goto error_end;
         }
@@ -487,31 +487,35 @@
         }
     }
 
-    if (quad_pos != 0) {
+    if (quad_pos == 1) {
+        /* There is exactly one extra valid, non-padding, base64 character.
+         * * This is an invalid length, as there is no possible input that
+         ** could encoded into such a base64 string.
+         */
         state = get_binascii_state(module);
-        if (state == NULL) {
-            /* error already set, from get_binascii_state */
-        } else if (quad_pos == 1) {
-            /*
-            ** There is exactly one extra valid, non-padding, base64 character.
-            ** This is an invalid length, as there is no possible input that
-            ** could encoded into such a base64 string.
-            */
+        if (state) {
             PyErr_Format(state->Error,
                          "Invalid base64-encoded string: "
                          "number of data characters (%zd) cannot be 1 more "
                          "than a multiple of 4",
                          (bin_data - bin_data_start) / 3 * 4 + 1);
-        } else {
+        }
+        goto error_end;
+    }
+
+    if (quad_pos != 0 && quad_pos + pads < 4) {
+        state = get_binascii_state(module);
+        if (state) {
             PyErr_SetString(state->Error, "Incorrect padding");
         }
-        error_end:
-        _PyBytesWriter_Dealloc(&writer);
-        return NULL;
+        goto error_end;
     }
 
-done:
     return _PyBytesWriter_Finish(&writer, bin_data);
+
+error_end:
+    _PyBytesWriter_Dealloc(&writer);
+    return NULL;
 }
 
 

++++++ CVE-2026-4786-webbrowser-open-action.patch ++++++
>From d57576d12bdcd9d86d527d81241e7faaa05c972c Mon Sep 17 00:00:00 2001
From: Stan Ulbrych <[email protected]>
Date: Mon, 13 Apr 2026 20:02:52 +0100
Subject: [PATCH] [3.11] 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.11.15/Lib/test/test_webbrowser.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_webbrowser.py     2026-04-25 
12:59:46.688833230 +0200
+++ Python-3.11.15/Lib/test/test_webbrowser.py  2026-04-25 12:59:46.742650302 
+0200
@@ -99,6 +99,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.11.15/Lib/webbrowser.py
===================================================================
--- Python-3.11.15.orig/Lib/webbrowser.py       2026-04-25 12:59:46.689165976 
+0200
+++ Python-3.11.15/Lib/webbrowser.py    2026-04-25 12:59:46.742825301 +0200
@@ -264,7 +264,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:
@@ -278,7 +277,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.11.15/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.11.15/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst
     2026-04-25 12:59:46.743018775 +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.11.15/Lib/http/cookies.py
===================================================================
--- Python-3.11.15.orig/Lib/http/cookies.py     2026-04-27 18:46:03.982786002 
+0200
+++ Python-3.11.15/Lib/http/cookies.py  2026-04-27 18:46:04.117463904 +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.11.15/Lib/test/test_http_cookies.py
===================================================================
--- Python-3.11.15.orig/Lib/test/test_http_cookies.py   2026-04-27 
18:46:03.983146511 +0200
+++ Python-3.11.15/Lib/test/test_http_cookies.py        2026-04-27 
18:46:04.118250229 +0200
@@ -1,5 +1,5 @@
 # Simple test suite for http/cookies.py
-
+import base64
 import copy
 import unittest
 import doctest
@@ -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.11.15/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.11.15/Misc/NEWS.d/next/Security/2026-04-21-13-46-30.gh-issue-90309.srvj9q.rst
      2026-04-27 18:46:04.118574830 +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 72d9d77abbb4a30885d244c4faf963082e0c1b24 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] [3.11] 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)

Co-authored-by: Stan Ulbrych <[email protected]>
---
 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.11.15/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.11.15/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst
     2026-04-24 23:04:46.062939247 +0200
@@ -0,0 +1,5 @@
+Fix a dangling input pointer in :class:`lzma.LZMADecompressor`,
+and :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.11.15/Modules/_bz2module.c
===================================================================
--- Python-3.11.15.orig/Modules/_bz2module.c    2026-03-03 01:52:57.000000000 
+0100
+++ Python-3.11.15/Modules/_bz2module.c 2026-04-24 23:04:46.062526709 +0200
@@ -595,6 +595,7 @@
     return result;
 
 error:
+    bzs->next_in = NULL;
     Py_XDECREF(result);
     return NULL;
 }
Index: Python-3.11.15/Modules/_lzmamodule.c
===================================================================
--- Python-3.11.15.orig/Modules/_lzmamodule.c   2026-03-03 01:52:57.000000000 
+0100
+++ Python-3.11.15/Modules/_lzmamodule.c        2026-04-24 23:04:46.062750672 
+0200
@@ -1105,6 +1105,7 @@
     return result;
 
 error:
+    lzs->next_in = NULL;
     Py_XDECREF(result);
     return NULL;
 }

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.1IDvUO/_old  2026-06-19 17:22:09.639693459 +0200
+++ /var/tmp/diff_new_pack.1IDvUO/_new  2026-06-19 17:22:09.643693596 +0200
@@ -1,6 +1,6 @@
-mtime: 1775598908
-commit: 74faae37ad8780b94fb71dd3921b3e672ecda40ae693a97c1dcdcfce5bf3b46e
-url: https://src.opensuse.org/python-interpreters/python311.git
-revision: 74faae37ad8780b94fb71dd3921b3e672ecda40ae693a97c1dcdcfce5bf3b46e
+mtime: 1780778098
+commit: 40ae616787d508cbe0e1213b14035fad0a6bc7a89e895ab247b215e6cb3dd4cb
+url: https://src.opensuse.org/python-interpreters/python311
+revision: 40ae616787d508cbe0e1213b14035fad0a6bc7a89e895ab247b215e6cb3dd4cb
 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-06-06 22:34:58.000000000 +0200
@@ -0,0 +1,7 @@
+_build.*
+*.obscpio
+*.osc
+.osc
+.pbuild
+python311-*-build/
+*.rej


++++++ python311-rpmlintrc ++++++
--- /var/tmp/diff_new_pack.1IDvUO/_old  2026-06-19 17:22:09.975705014 +0200
+++ /var/tmp/diff_new_pack.1IDvUO/_new  2026-06-19 17:22:09.983705289 +0200
@@ -1,5 +1,5 @@
-addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
-addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
-addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")
+addFilter("pem-certificate.*/usr/lib.*/python.*/test/.*.pem")
+addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/.*.c")
+addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/.*.cpp")
 addFilter("python-bytecode-inconsistent-mtime.*\.pyc")
 

Reply via email to