Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python312 for openSUSE:Factory 
checked in at 2026-04-01 19:51:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python312 (Old)
 and      /work/SRC/openSUSE:Factory/.python312.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python312"

Wed Apr  1 19:51:32 2026 rev:47 rq:1343943 version:3.12.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/python312/python312.changes      2026-03-22 
14:13:01.471461536 +0100
+++ /work/SRC/openSUSE:Factory/.python312.new.21863/python312.changes   
2026-04-01 19:52:31.613860909 +0200
@@ -1,0 +2,28 @@
+Fri Mar 27 17:51:07 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add CVE-2026-4519-webbrowser-open-dashes.patch to reject
+  leading dashes in webbrowser URLs (bsc#1260026, CVE-2026-4519,
+  gh#python/cpython#143930).
+
+-------------------------------------------------------------------
+Wed Mar 25 16:40:18 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add CVE-2025-13462-tarinfo-header-parse.patch which skips
+  TarInfo DIRTYPE normalization during GNU long name handling
+  (bsc#1259611, CVE-2025-13462).
+
+-------------------------------------------------------------------
+Mon Mar 23 22:16:01 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add CVE-2026-4224-expat-unbound-C-recursion.patch avoiding
+  unbound C recursion in conv_content_model in pyexpat.c
+  (bsc#1259735, CVE-2026-4224).
+
+-------------------------------------------------------------------
+Mon Mar 23 17:15:50 UTC 2026 - Matej Cepl <[email protected]>
+
+- Add CVE-2026-3644-cookies-Morsel-update-II.patch to reject
+  control characters in http.cookies.Morsel.update() and
+  http.cookies.BaseCookie.js_output (bsc#1259734, CVE-2026-3644).
+
+-------------------------------------------------------------------

New:
----
  CVE-2025-13462-tarinfo-header-parse.patch
  CVE-2026-3644-cookies-Morsel-update-II.patch
  CVE-2026-4224-expat-unbound-C-recursion.patch
  CVE-2026-4519-webbrowser-open-dashes.patch

----------(New B)----------
  New:
- Add CVE-2025-13462-tarinfo-header-parse.patch which skips
  TarInfo DIRTYPE normalization during GNU long name handling
  New:
- Add CVE-2026-3644-cookies-Morsel-update-II.patch to reject
  control characters in http.cookies.Morsel.update() and
  New:
- Add CVE-2026-4224-expat-unbound-C-recursion.patch avoiding
  unbound C recursion in conv_content_model in pyexpat.c
  New:
- Add CVE-2026-4519-webbrowser-open-dashes.patch to reject
  leading dashes in webbrowser URLs (bsc#1260026, CVE-2026-4519,
----------(New E)----------

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

Other differences:
------------------
++++++ python312.spec ++++++
--- /var/tmp/diff_new_pack.aTg06e/_old  2026-04-01 19:52:33.841953746 +0200
+++ /var/tmp/diff_new_pack.aTg06e/_new  2026-04-01 19:52:33.845953913 +0200
@@ -204,6 +204,18 @@
 # PATCH-FIX-UPSTREAM CVE-2026-2297-SourcelessFileLoader-io_open_code.patch 
bsc#1259240 [email protected]
 # Ensure SourcelessFileLoader uses io.open_code
 Patch59:        CVE-2026-2297-SourcelessFileLoader-io_open_code.patch
+# PATCH-FIX-UPSTREAM CVE-2026-3644-cookies-Morsel-update-II.patch bsc#1259734 
[email protected]
+# Reject control characters in http.cookies.Morsel.update() and 
http.cookies.BaseCookie.js_output
+Patch60:        CVE-2026-3644-cookies-Morsel-update-II.patch
+# PATCH-FIX-UPSTREAM CVE-2026-4224-expat-unbound-C-recursion.patch bsc#1259735 
[email protected]
+# Avoid unbound C recursion in conv_content_model
+Patch61:        CVE-2026-4224-expat-unbound-C-recursion.patch
+# PATCH-FIX-UPSTREAM CVE-2025-13462-tarinfo-header-parse.patch bsc#1259611 
[email protected]
+# Skip TarInfo DIRTYPE normalization during GNU long name handling
+Patch62:        CVE-2025-13462-tarinfo-header-parse.patch
+# PATCH-FIX-UPSTREAM CVE-2026-4519-webbrowser-open-dashes.patch bsc#1260026 
[email protected]
+# reject leading dashes in webbrowser URLs
+Patch63:        CVE-2026-4519-webbrowser-open-dashes.patch
 ### END OF PATCHES
 BuildRequires:  autoconf-archive
 BuildRequires:  automake

++++++ CVE-2025-13462-tarinfo-header-parse.patch ++++++
>From 0540c4e0592544c57b55709b5426342e471b2b8f Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Wed, 11 Mar 2026 08:47:55 -0500
Subject: [PATCH] gh-141707: Skip TarInfo DIRTYPE normalization during GNU long
 name handling (cherry picked from commit
 42d754e34c06e57ad6b8e7f92f32af679912d8ab)

Co-authored-by: Seth Michael Larson <[email protected]>
Co-authored-by: Eashwar Ranganathan <[email protected]>
---
 Lib/tarfile.py                                                          |   29 
++++++++--
 Lib/test/test_tarfile.py                                                |   19 
++++++
 Misc/ACKS                                                               |    1 
 Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst |    2 
 4 files changed, 47 insertions(+), 4 deletions(-)
 create mode 100644 
Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst

Index: Python-3.12.13/Lib/tarfile.py
===================================================================
--- Python-3.12.13.orig/Lib/tarfile.py  2026-03-26 00:11:27.447776557 +0100
+++ Python-3.12.13/Lib/tarfile.py       2026-03-26 00:11:51.131015643 +0100
@@ -1245,6 +1245,20 @@
     @classmethod
     def frombuf(cls, buf, encoding, errors):
         """Construct a TarInfo object from a 512 byte bytes object.
+
+        To support the old v7 tar format AREGTYPE headers are
+        transformed to DIRTYPE headers if their name ends in '/'.
+        """
+        return cls._frombuf(buf, encoding, errors)
+
+    @classmethod
+    def _frombuf(cls, buf, encoding, errors, *, dircheck=True):
+        """Construct a TarInfo object from a 512 byte bytes object.
+
+        If ``dircheck`` is set to ``True`` then ``AREGTYPE`` headers will
+        be normalized to ``DIRTYPE`` if the name ends in a trailing slash.
+        ``dircheck`` must be set to ``False`` if this function is called
+        on a follow-up header such as ``GNUTYPE_LONGNAME``.
         """
         if len(buf) == 0:
             raise EmptyHeaderError("empty header")
@@ -1275,7 +1289,7 @@
 
         # Old V7 tar format represents a directory as a regular
         # file with a trailing slash.
-        if obj.type == AREGTYPE and obj.name.endswith("/"):
+        if dircheck and obj.type == AREGTYPE and obj.name.endswith("/"):
             obj.type = DIRTYPE
 
         # The old GNU sparse format occupies some of the unused
@@ -1310,8 +1324,15 @@
         """Return the next TarInfo object from TarFile object
            tarfile.
         """
+        return cls._fromtarfile(tarfile)
+
+    @classmethod
+    def _fromtarfile(cls, tarfile, *, dircheck=True):
+        """
+        See dircheck documentation in _frombuf().
+        """
         buf = tarfile.fileobj.read(BLOCKSIZE)
-        obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
+        obj = cls._frombuf(buf, tarfile.encoding, tarfile.errors, 
dircheck=dircheck)
         obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
         return obj._proc_member(tarfile)
 
@@ -1369,7 +1390,7 @@
 
         # Fetch the next header and process it.
         try:
-            next = self.fromtarfile(tarfile)
+            next = self._fromtarfile(tarfile, dircheck=False)
         except HeaderError as e:
             raise SubsequentHeaderError(str(e)) from None
 
@@ -1504,7 +1525,7 @@
 
         # Fetch the next header.
         try:
-            next = self.fromtarfile(tarfile)
+            next = self._fromtarfile(tarfile, dircheck=False)
         except HeaderError as e:
             raise SubsequentHeaderError(str(e)) from None
 
Index: Python-3.12.13/Lib/test/test_tarfile.py
===================================================================
--- Python-3.12.13.orig/Lib/test/test_tarfile.py        2026-03-26 
00:11:36.364866576 +0100
+++ Python-3.12.13/Lib/test/test_tarfile.py     2026-03-26 00:11:51.134015673 
+0100
@@ -1134,6 +1134,25 @@
                 self.assertIsNotNone(tar.getmember(longdir))
                 self.assertIsNotNone(tar.getmember(longdir.removesuffix('/')))
 
+    def test_longname_file_not_directory(self):
+        # Test reading a longname file and ensure it is not handled as a 
directory
+        # Issue #141707
+        buf = io.BytesIO()
+        with tarfile.open(mode='w', fileobj=buf, format=self.format) as tar:
+            ti = tarfile.TarInfo()
+            ti.type = tarfile.AREGTYPE
+            ti.name = ('a' * 99) + '/' + ('b' * 3)
+            tar.addfile(ti)
+
+            expected = {t.name: t.type for t in tar.getmembers()}
+
+        buf.seek(0)
+        with tarfile.open(mode='r', fileobj=buf) as tar:
+            actual = {t.name: t.type for t in tar.getmembers()}
+
+        self.assertEqual(expected, actual)
+
+
 class GNUReadTest(LongnameTest, ReadTest, unittest.TestCase):
 
     subdir = "gnu"
Index: Python-3.12.13/Misc/ACKS
===================================================================
--- Python-3.12.13.orig/Misc/ACKS       2026-03-03 13:39:30.000000000 +0100
+++ Python-3.12.13/Misc/ACKS    2026-03-26 00:11:51.135015683 +0100
@@ -1492,6 +1492,7 @@
 Ashwin Ramaswami
 Jeff Ramnani
 Bayard Randel
+Eashwar Ranganathan
 Varpu Rantala
 Brodie Rao
 Rémi Rampin
Index: 
Python-3.12.13/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.13/Misc/NEWS.d/next/Library/2025-11-18-06-35-53.gh-issue-141707.DBmQIy.rst
      2026-03-26 00:11:51.136028525 +0100
@@ -0,0 +1,2 @@
+Don't change :class:`tarfile.TarInfo` type from ``AREGTYPE`` to ``DIRTYPE`` 
when parsing
+GNU long name or link headers.

++++++ CVE-2026-3644-cookies-Morsel-update-II.patch ++++++
>From 736de53d3d91e83e9ff8a5d81b418bd8ea033e35 Mon Sep 17 00:00:00 2001
From: Stan Ulbrych <[email protected]>
Date: Mon, 16 Mar 2026 13:43:43 +0000
Subject: [PATCH] gh-145599, CVE 2026-3644: Reject control characters in
 `http.cookies.Morsel.update()` (GH-145600)

Reject control characters in `http.cookies.Morsel.update()` and 
`http.cookies.BaseCookie.js_output`.
(cherry picked from commit 57e88c1cf95e1481b94ae57abe1010469d47a6b4)

Co-authored-by: Stan Ulbrych <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
---
 Lib/http/cookies.py                                                      |   
24 +++++-
 Lib/test/test_http_cookies.py                                            |   
38 ++++++++++
 Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst |    
4 +
 3 files changed, 62 insertions(+), 4 deletions(-)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst

Index: Python-3.12.13/Lib/http/cookies.py
===================================================================
--- Python-3.12.13.orig/Lib/http/cookies.py     2026-03-23 18:31:24.882402102 
+0100
+++ Python-3.12.13/Lib/http/cookies.py  2026-03-23 18:32:06.098683524 +0100
@@ -335,9 +335,16 @@
             key = key.lower()
             if key not in self._reserved:
                 raise CookieError("Invalid attribute %r" % (key,))
+            if _has_control_character(key, val):
+                raise CookieError("Control characters are not allowed in "
+                                  f"cookies {key!r} {val!r}")
             data[key] = val
         dict.update(self, data)
 
+    def __ior__(self, values):
+        self.update(values)
+        return self
+
     def isReservedKey(self, K):
         return K.lower() in self._reserved
 
@@ -363,9 +370,15 @@
         }
 
     def __setstate__(self, state):
-        self._key = state['key']
-        self._value = state['value']
-        self._coded_value = state['coded_value']
+        key = state['key']
+        value = state['value']
+        coded_value = state['coded_value']
+        if _has_control_character(key, value, coded_value):
+            raise CookieError("Control characters are not allowed in cookies "
+                              f"{key!r} {value!r} {coded_value!r}")
+        self._key = key
+        self._value = value
+        self._coded_value = coded_value
 
     def output(self, attrs=None, header="Set-Cookie:"):
         return "%s %s" % (header, self.OutputString(attrs))
@@ -377,13 +390,16 @@
 
     def js_output(self, attrs=None):
         # Print javascript
+        output_string = self.OutputString(attrs)
+        if _has_control_character(output_string):
+            raise CookieError("Control characters are not allowed in cookies")
         return """
         <script type="text/javascript">
         <!-- begin hiding
         document.cookie = \"%s\";
         // end hiding -->
         </script>
-        """ % (self.OutputString(attrs).replace('"', r'\"'))
+        """ % (output_string.replace('"', r'\"'))
 
     def OutputString(self, attrs=None):
         # Build up our result
Index: Python-3.12.13/Lib/test/test_http_cookies.py
===================================================================
--- Python-3.12.13.orig/Lib/test/test_http_cookies.py   2026-03-23 
18:31:26.797590700 +0100
+++ Python-3.12.13/Lib/test/test_http_cookies.py        2026-03-23 
18:32:06.098900964 +0100
@@ -573,6 +573,14 @@
             with self.assertRaises(cookies.CookieError):
                 morsel["path"] = c0
 
+            # .__setstate__()
+            with self.assertRaises(cookies.CookieError):
+                morsel.__setstate__({'key': c0, 'value': 'val', 'coded_value': 
'coded'})
+            with self.assertRaises(cookies.CookieError):
+                morsel.__setstate__({'key': 'key', 'value': c0, 'coded_value': 
'coded'})
+            with self.assertRaises(cookies.CookieError):
+                morsel.__setstate__({'key': 'key', 'value': 'val', 
'coded_value': c0})
+
             # .setdefault()
             with self.assertRaises(cookies.CookieError):
                 morsel.setdefault("path", c0)
@@ -587,6 +595,18 @@
             with self.assertRaises(cookies.CookieError):
                 morsel.set("path", "val", c0)
 
+            # .update()
+            with self.assertRaises(cookies.CookieError):
+                morsel.update({"path": c0})
+            with self.assertRaises(cookies.CookieError):
+                morsel.update({c0: "val"})
+
+            # .__ior__()
+            with self.assertRaises(cookies.CookieError):
+                morsel |= {"path": c0}
+            with self.assertRaises(cookies.CookieError):
+                morsel |= {c0: "val"}
+
     def test_control_characters_output(self):
         # Tests that even if the internals of Morsel are modified
         # that a call to .output() has control character safeguards.
@@ -607,6 +627,24 @@
             with self.assertRaises(cookies.CookieError):
                 cookie.output()
 
+        # Tests that .js_output() also has control character safeguards.
+        for c0 in support.control_characters_c0():
+            morsel = cookies.Morsel()
+            morsel.set("key", "value", "coded-value")
+            morsel._key = c0  # Override private variable.
+            cookie = cookies.SimpleCookie()
+            cookie["cookie"] = morsel
+            with self.assertRaises(cookies.CookieError):
+                cookie.js_output()
+
+            morsel = cookies.Morsel()
+            morsel.set("key", "value", "coded-value")
+            morsel._coded_value = c0  # Override private variable.
+            cookie = cookies.SimpleCookie()
+            cookie["cookie"] = morsel
+            with self.assertRaises(cookies.CookieError):
+                cookie.js_output()
+
 
 def load_tests(loader, tests, pattern):
     tests.addTest(doctest.DocTestSuite(cookies))
Index: 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-03-06-17-03-38.gh-issue-145599.kchwZV.rst
     2026-03-23 18:32:06.099117222 +0100
@@ -0,0 +1,4 @@
+Reject control characters in :class:`http.cookies.Morsel`
+:meth:`~http.cookies.Morsel.update` and
+:meth:`~http.cookies.BaseCookie.js_output`.
+This addresses :cve:`2026-3644`.

++++++ CVE-2026-4224-expat-unbound-C-recursion.patch ++++++
>From e5caf45faac74b0ed869e3336420cffd3510ce6e Mon Sep 17 00:00:00 2001
From: Stan Ulbrych <[email protected]>
Date: Sun, 15 Mar 2026 21:46:06 +0000
Subject: [PATCH] [3.12] gh-145986: Avoid unbound C recursion in
 `conv_content_model` in `pyexpat.c` (CVE 2026-4224) (GH-145987)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fix C stack overflow (CVE-2026-4224) when an Expat parser
with a registered `ElementDeclHandler` parses inline DTD
containing deeply nested content model.

---------
(cherry picked from commit eb0e8be3a7e11b87d198a2c3af1ed0eccf532768)

Co-authored-by: Stan Ulbrych <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>
---
 Lib/test/test_pyexpat.py                                                 |   
18 ++++++++++
 Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst |    
4 ++
 Modules/pyexpat.c                                                        |    
9 ++++-
 3 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst

Index: Python-3.12.13/Lib/test/test_pyexpat.py
===================================================================
--- Python-3.12.13.orig/Lib/test/test_pyexpat.py        2026-03-24 
09:34:51.805858845 +0100
+++ Python-3.12.13/Lib/test/test_pyexpat.py     2026-03-24 09:34:54.824243016 
+0100
@@ -675,6 +675,24 @@
         parser.Parse(xml2, True)
         self.assertEqual(self.n, 4)
 
+class ElementDeclHandlerTest(unittest.TestCase):
+    def test_deeply_nested_content_model(self):
+        # This should raise a RecursionError and not crash.
+        # See https://github.com/python/cpython/issues/145986.
+        N = 500_000
+        data = (
+            b'<!DOCTYPE root [\n<!ELEMENT root '
+            + b'(a, ' * N + b'a' + b')' * N
+            + b'>\n]>\n<root/>\n'
+        )
+
+        parser = expat.ParserCreate()
+        parser.ElementDeclHandler = lambda _1, _2: None
+        with support.infinite_recursion():
+            with self.assertRaises(RecursionError):
+                parser.Parse(data)
+
+
 class MalformedInputTest(unittest.TestCase):
     def test1(self):
         xml = b"\0\r\n"
Index: 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-03-14-17-31-39.gh-issue-145986.ifSSr8.rst
     2026-03-24 09:34:54.824722198 +0100
@@ -0,0 +1,4 @@
+:mod:`xml.parsers.expat`: Fixed a crash caused by unbounded C recursion when
+converting deeply nested XML content models with
+:meth:`~xml.parsers.expat.xmlparser.ElementDeclHandler`.
+This addresses :cve:`2026-4224`.
Index: Python-3.12.13/Modules/pyexpat.c
===================================================================
--- Python-3.12.13.orig/Modules/pyexpat.c       2026-03-03 13:39:30.000000000 
+0100
+++ Python-3.12.13/Modules/pyexpat.c    2026-03-24 09:34:54.825160064 +0100
@@ -3,6 +3,7 @@
 #endif
 
 #include "Python.h"
+#include "pycore_ceval.h"           // _Py_EnterRecursiveCall()
 #include "pycore_runtime.h"         // _Py_ID()
 #include <ctype.h>
 
@@ -578,6 +579,10 @@
 conv_content_model(XML_Content * const model,
                    PyObject *(*conv_string)(const XML_Char *))
 {
+    if (_Py_EnterRecursiveCall(" in conv_content_model")) {
+        return NULL;
+    }
+
     PyObject *result = NULL;
     PyObject *children = PyTuple_New(model->numchildren);
     int i;
@@ -589,7 +594,7 @@
                                                  conv_string);
             if (child == NULL) {
                 Py_XDECREF(children);
-                return NULL;
+                goto done;
             }
             PyTuple_SET_ITEM(children, i, child);
         }
@@ -597,6 +602,8 @@
                                model->type, model->quant,
                                conv_string,model->name, children);
     }
+done:
+    _Py_LeaveRecursiveCall();
     return result;
 }
 

++++++ CVE-2026-4519-webbrowser-open-dashes.patch ++++++
>From d498b7e55b603ef9c80508ed8eb9556a1156f49e Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Fri, 20 Mar 2026 09:47:13 -0500
Subject: [PATCH 1/2] gh-143930: Reject leading dashes in webbrowser URLs
 (cherry picked from commit 82a24a4442312bdcfc4c799885e8b3e00990f02b)

---
 Lib/test/test_webbrowser.py                                              |    
5 ++++
 Lib/webbrowser.py                                                        |   
12 ++++++++++
 Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst |    
1 
 3 files changed, 18 insertions(+)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst

Index: Python-3.12.13/Lib/test/test_webbrowser.py
===================================================================
--- Python-3.12.13.orig/Lib/test/test_webbrowser.py     2026-03-27 
20:07:52.032965514 +0100
+++ Python-3.12.13/Lib/test/test_webbrowser.py  2026-03-27 20:07:54.695959647 
+0100
@@ -59,6 +59,11 @@
                    options=[],
                    arguments=[URL])
 
+    def test_reject_dash_prefixes(self):
+        browser = self.browser_class(name=CMD_NAME)
+        with self.assertRaises(ValueError):
+            browser.open(f"--key=val {URL}")
+
 
 class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase):
 
Index: Python-3.12.13/Lib/webbrowser.py
===================================================================
--- Python-3.12.13.orig/Lib/webbrowser.py       2026-03-27 20:07:52.424551572 
+0100
+++ Python-3.12.13/Lib/webbrowser.py    2026-03-27 20:07:54.697002945 +0100
@@ -157,6 +157,12 @@
     def open_new_tab(self, url):
         return self.open(url, 2)
 
+    @staticmethod
+    def _check_url(url):
+        """Ensures that the URL is safe to pass to subprocesses as a 
parameter"""
+        if url and url.lstrip().startswith("-"):
+            raise ValueError(f"Invalid URL: {url}")
+
 
 class GenericBrowser(BaseBrowser):
     """Class for all browsers started with a command
@@ -174,6 +180,7 @@
 
     def open(self, url, new=0, autoraise=True):
         sys.audit("webbrowser.open", url)
+        self._check_url(url)
         cmdline = [self.name] + [arg.replace("%s", url)
                                  for arg in self.args]
         try:
@@ -194,6 +201,7 @@
         cmdline = [self.name] + [arg.replace("%s", url)
                                  for arg in self.args]
         sys.audit("webbrowser.open", url)
+        self._check_url(url)
         try:
             if sys.platform[:3] == 'win':
                 p = subprocess.Popen(cmdline)
@@ -259,6 +267,7 @@
 
     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:
@@ -349,6 +358,7 @@
 
     def open(self, url, new=0, autoraise=True):
         sys.audit("webbrowser.open", url)
+        self._check_url(url)
         # XXX Currently I know no way to prevent KFM from opening a new win.
         if new == 2:
             action = "newTab"
@@ -553,6 +563,7 @@
     class WindowsDefault(BaseBrowser):
         def open(self, url, new=0, autoraise=True):
             sys.audit("webbrowser.open", url)
+            self._check_url(url)
             try:
                 os.startfile(url)
             except OSError:
@@ -637,6 +648,7 @@
 
         def open(self, url, new=0, autoraise=True):
             sys.audit("webbrowser.open", url)
+            self._check_url(url)
             if self.name == 'default':
                 script = 'open location "%s"' % url.replace('"', '%22') # 
opens in default browser
             else:
Index: 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.13/Misc/NEWS.d/next/Security/2026-01-16-12-04-49.gh-issue-143930.zYC5x3.rst
     2026-03-27 20:07:54.696345345 +0100
@@ -0,0 +1 @@
+Reject leading dashes in URLs passed to :func:`webbrowser.open`


++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.aTg06e/_old  2026-04-01 19:52:34.369975747 +0200
+++ /var/tmp/diff_new_pack.aTg06e/_new  2026-04-01 19:52:34.381976247 +0200
@@ -1,6 +1,6 @@
-mtime: 1773872449
-commit: a9c01d924fedbb9358b3af56446e137743065ef6476ddb946ef96503b87cb60c
+mtime: 1774638495
+commit: 728d2eeb5ff26c6b39b0ed4b240254dbbbfc4d9869cb9fa899363dbf1dfadf80
 url: https://src.opensuse.org/python-interpreters/python312.git
-revision: a9c01d924fedbb9358b3af56446e137743065ef6476ddb946ef96503b87cb60c
+revision: 728d2eeb5ff26c6b39b0ed4b240254dbbbfc4d9869cb9fa899363dbf1dfadf80
 projectscmsync: https://src.opensuse.org/python-interpreters/_ObsPrj
 

++++++ build.specials.obscpio ++++++
--- old/.gitignore      2026-03-18 23:21:15.000000000 +0100
+++ new/.gitignore      2026-03-27 20:08:32.000000000 +0100
@@ -1,5 +1,6 @@
-.osc
-*.obscpio
 _build.*
+*.obscpio
+*.osc
+.osc
 .pbuild
 python312-3.12.*-build

++++++ 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-03-27 20:08:32.000000000 +0100
@@ -0,0 +1,6 @@
+_build.*
+*.obscpio
+*.osc
+.osc
+.pbuild
+python312-3.12.*-build

Reply via email to