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-02-18 17:04:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python312 (Old)
 and      /work/SRC/openSUSE:Factory/.python312.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python312"

Wed Feb 18 17:04:55 2026 rev:43 rq:1332782 version:3.12.12

Changes:
--------
--- /work/SRC/openSUSE:Factory/python312/python312.changes      2025-12-29 
15:15:46.188461740 +0100
+++ /work/SRC/openSUSE:Factory/.python312.new.1977/python312.changes    
2026-02-18 17:05:18.261410406 +0100
@@ -1,0 +2,26 @@
+Fri Feb  6 00:07:20 CET 2026 - Matej Cepl <[email protected]>
+  
+- CVE-2025-11468: to preserve parens when folding comments.
+  (bsc#1257029, gh#python/cpython#143935)
+  CVE-2025-11468-email-hdr-fold-comment.patch
+- CVE-2025-12781: fix decoding with non-standard Base64 alphabet
+  (bsc#1257108, gh#python/cpython#125346)
+  CVE-2025-12781-b64decode-alt-chars.patch
+- CVE-2026-0672: rejects control characters in http cookies.
+  (bsc#1257031, gh#python/cpython#143919)
+  CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
+- CVE-2026-0865: rejecting control characters in
+  wsgiref.headers.Headers, which could be abused for injecting
+  false HTTP headers. (bsc#1257042, gh#python/cpython#143916)
+  CVE-2026-0865-wsgiref-ctrl-chars.patch
+- CVE-2025-15366: basically the same as the previous patch for
+  IMAP protocol. (bsc#1257044, gh#python/cpython#143921)
+  CVE-2025-15366-imap-ctrl-chars.patch
+- CVE-2025-15282: basically the same as the previous patch for
+  urllib library. (bsc#1257046, gh#python/cpython#143925)
+  CVE-2025-15282-urllib-ctrl-chars.patch
+- CVE-2025-15367: basically the same as the previous patch for
+  poplib library. (bsc#1257041, gh#python/cpython#143923)
+  CVE-2025-15367-poplib-ctrl-chars.patch
+
+-------------------------------------------------------------------
@@ -4,2 +30 @@
-- Add CVE-2025-13836-http-resp-cont-len.patch (bsc#1254400,
-  CVE-2025-13836) to prevent reading an HTTP response from
+- CVE-2025-13836: to prevent reading an HTTP response from
@@ -7,7 +32,9 @@
-  Content-Length per default as the length.
-- Add CVE-2025-12084-minidom-quad-search.patch prevent quadratic
-  behavior in node ID cache clearing (CVE-2025-12084,
-  bsc#1254997).
-- Add CVE-2025-13837-plistlib-mailicious-length.patch protect
-  against OOM when loading malicious content (CVE-2025-13837,
-  bsc#1254401).
+  Content-Length per default as the length. (bsc#1254400,
+  gh#python/cpython#119451)
+  CVE-2025-13836-http-resp-cont-len.patch
+- CVE-2025-12084: prevent quadratic behavior in node ID cache
+  clearing. (bsc#1254997, gh#python/cpython#142145)
+  CVE-2025-12084-minidom-quad-search.patch
+- CVE-2025-13837: protect against OOM when loading malicious
+  content. (bsc#1254401, gh#python/cpython#119342)
+  CVE-2025-13837-plistlib-mailicious-length.patch
@@ -1211,4 +1238,4 @@
-    - gh-99242: os.getloadavg() may throw OSError when
-      running regression tests under certain conditions (e.g.
-      chroot). This error is now caught and ignored, since
-      reporting load average is optional.
+    - gh-99242: os.getloadavg() may throw OSError when running
+      regression tests under certain conditions (e.g. chroot).
+      This error is now caught and ignored, since reporting load
+      average is optional.
@@ -1219,11 +1246,9 @@
-    - gh-121160: Add a test for
-      readline.set_history_length(). Note that this test may fail
-      on readline libraries.
-    - gh-121200: Fix test_expanduser_pwd2() of
-      test_posixpath. Call getpwnam() to get pw_dir, since it
-      can be different than getpwall() pw_dir. Patch by Victor
-      Stinner.
-    - gh-121188: When creating the JUnit XML file, regrtest
-      now escapes characters which are invalid in XML, such
-      as the chr(27) control character used in ANSI escape
-      sequences. Patch by Victor Stinner.
+    - gh-121160: Add a test for readline.set_history_length().
+      Note that this test may fail on readline libraries.
+    - gh-121200: Fix test_expanduser_pwd2() of test_posixpath.
+      Call getpwnam() to get pw_dir, since it can be different
+      than getpwall() pw_dir. Patch by Victor Stinner.
+    - gh-121188: When creating the JUnit XML file, regrtest now
+      escapes characters which are invalid in XML, such as the
+      chr(27) control character used in ANSI escape sequences.
+      Patch by Victor Stinner.
@@ -1252,6 +1277,6 @@
-    - gh-121650: email headers with embedded newlines are
-      now quoted on output. The generator will now refuse to
-      serialize (write) headers that are unsafely folded or
-      delimited; see verify_generated_headers. (Contributed by
-      Bas Bloemsaat and Petr Viktorin in gh-121650; bsc#1228780,
-      CVE-2024-6923).
+    - CVE-2026-1299 and CVE-2024-6923: email headers with
+      embedded newlines are now quoted on output. The generator
+      will now refuse to serialize (write) headers that are
+      unsafely folded or delimited; see verify_generated_headers.
+      (Contributed by Bas Bloemsaat and Petr Viktorin in
+      bsc#1228780, gh-121650; bsc#1257181, gh-121650).
@@ -1294,2 +1319,2 @@
-    - gh-120495: Fix incorrect exception handling in Tab
-      Nanny. Patch by Wulian233.
+    - gh-120495: Fix incorrect exception handling in Tab Nanny.
+      Patch by Wulian233.
@@ -1304,3 +1329,3 @@
-      would produce incorrect results if type parameters in a
-      class scope were overridden by assignments in a class scope
-      and from __future__ import annotations semantics were
+      would produce incorrect results if type parameters in
+      a class scope were overridden by assignments in a class
+      scope and from __future__ import annotations semantics were
@@ -1331,5 +1356,5 @@
-    - gh-81936: help() and showtopic() methods now respect a
-      configured output argument to pydoc.Helper and not use the
-      pager in such cases. Patch by Enrico Tröger.
-    - gh-119577: The DeprecationWarning emitted when testing
-      the truth value of an xml.etree.ElementTree.Element now
+    - gh-81936: help() and showtopic() methods now respect
+      a configured output argument to pydoc.Helper and not use
+      the pager in such cases. Patch by Enrico Tröger.
+    - gh-119577: The DeprecationWarning emitted when testing the
+      truth value of an xml.etree.ElementTree.Element now
@@ -1364,2 +1389,2 @@
-    - gh-121871: Documentation HTML varies from timestamp. Patch by
-      Bernhard M. Wiedemann (bsc#1227999).
+    - gh-121871: Documentation HTML varies from timestamp. Patch
+      by Bernhard M. Wiedemann (bsc#1227999).
@@ -1372,2 +1397,2 @@
-    - gh-122029: Emit c_call events in sys.setprofile() when a
-      PyMethodObject pointing to a PyCFunction is called.
+    - gh-122029: Emit c_call events in sys.setprofile() when
+      a PyMethodObject pointing to a PyCFunction is called.
@@ -1390,2 +1415,2 @@
-      modification of a list object, where one thread assigns a
-      slice and another clears it.
+      modification of a list object, where one thread assigns
+      a slice and another clears it.
@@ -1393,2 +1418,2 @@
-      bytes and bytearray objects when using protocol version
-      5. Patch by Bénédikt Tran.
+      bytes and bytearray objects when using protocol version 5.
+      Patch by Bénédikt Tran.

New:
----
  CVE-2025-11468-email-hdr-fold-comment.patch
  CVE-2025-12781-b64decode-alt-chars.patch
  CVE-2025-15282-urllib-ctrl-chars.patch
  CVE-2025-15366-imap-ctrl-chars.patch
  CVE-2025-15367-poplib-ctrl-chars.patch
  CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
  CVE-2026-0865-wsgiref-ctrl-chars.patch

----------(New B)----------
  New:  (bsc#1257029, gh#python/cpython#143935)
  CVE-2025-11468-email-hdr-fold-comment.patch
- CVE-2025-12781: fix decoding with non-standard Base64 alphabet
  New:  (bsc#1257108, gh#python/cpython#125346)
  CVE-2025-12781-b64decode-alt-chars.patch
- CVE-2026-0672: rejects control characters in http cookies.
  New:  urllib library. (bsc#1257046, gh#python/cpython#143925)
  CVE-2025-15282-urllib-ctrl-chars.patch
- CVE-2025-15367: basically the same as the previous patch for
  New:  IMAP protocol. (bsc#1257044, gh#python/cpython#143921)
  CVE-2025-15366-imap-ctrl-chars.patch
- CVE-2025-15282: basically the same as the previous patch for
  New:  poplib library. (bsc#1257041, gh#python/cpython#143923)
  CVE-2025-15367-poplib-ctrl-chars.patch
  New:  (bsc#1257031, gh#python/cpython#143919)
  CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
- CVE-2026-0865: rejecting control characters in
  New:  false HTTP headers. (bsc#1257042, gh#python/cpython#143916)
  CVE-2026-0865-wsgiref-ctrl-chars.patch
- CVE-2025-15366: basically the same as the previous patch for
----------(New E)----------

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

Other differences:
------------------
++++++ python312.spec ++++++
--- /var/tmp/diff_new_pack.vwuuUW/_old  2026-02-18 17:05:21.597549260 +0100
+++ /var/tmp/diff_new_pack.vwuuUW/_new  2026-02-18 17:05:21.601549426 +0100
@@ -204,6 +204,28 @@
 # PATCH-FIX-UPSTREAM CVE-2025-13837-plistlib-mailicious-length.patch 
bsc#1254401 [email protected]
 # protect against OOM when loading malicious content
 Patch51:        CVE-2025-13837-plistlib-mailicious-length.patch 
+# PATCH-FIX-UPSTREAM CVE-2025-11468-email-hdr-fold-comment.patch bsc#1257029 
[email protected]
+# Email preserve parens when folding comments
+Patch52:        CVE-2025-11468-email-hdr-fold-comment.patch
+# PATCH-FIX-UPSTREAM CVE-2025-12781-b64decode-alt-chars.patch bsc#1257108 
[email protected]
+# Fix decoding with non-standard Base64 alphabet gh#python/cpython#125346
+Patch53:        CVE-2025-12781-b64decode-alt-chars.patch
+# PATCH-FIX-UPSTREAM CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch 
bsc#1257031 [email protected]
+# Reject control characters in http cookies
+Patch54:        CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch
+# PATCH-FIX-UPSTREAM CVE-2026-0865-wsgiref-ctrl-chars.patch bsc#1257042 
[email protected]
+# Reject control characters in wsgiref.headers.Headers
+Patch55:        CVE-2026-0865-wsgiref-ctrl-chars.patch
+# PATCH-FIX-UPSTREAM CVE-2025-15366-imap-ctrl-chars.patch bsc#1257044 
[email protected]
+# Reject control characters in wsgiref.headers.Headers
+Patch56:        CVE-2025-15366-imap-ctrl-chars.patch
+# PATCH-FIX-UPSTREAM CVE-2025-15282-urllib-ctrl-chars.patch bsc#1257046 
[email protected]
+# Reject control characters in urllib
+Patch57:        CVE-2025-15282-urllib-ctrl-chars.patch
+# PATCH-FIX-UPSTREAM CVE-2025-15367-poplib-ctrl-chars.patch bsc#1257041 
[email protected]
+# Reject control characters in poplib
+Patch58:        CVE-2025-15367-poplib-ctrl-chars.patch
+### END OF PATCHES
 BuildRequires:  autoconf-archive
 BuildRequires:  automake
 BuildRequires:  fdupes

++++++ CVE-2025-11468-email-hdr-fold-comment.patch ++++++
>From 3900a2cb7d8321629717b8483179263a968bf552 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Mon, 19 Jan 2026 06:38:22 -0600
Subject: [PATCH] gh-143935: Email preserve parens when folding comments
 (GH-143936)

Fix a bug in the folding of comments when flattening an email message
using a modern email policy. Comments consisting of a very long sequence of
non-foldable characters could trigger a forced line wrap that omitted the
required leading space on the continuation line, causing the remainder of
the comment to be interpreted as a new header field. This enabled header
injection with carefully crafted inputs.
(cherry picked from commit 17d1490aa97bd6b98a42b1a9b324ead84e7fd8a2)

Co-authored-by: Seth Michael Larson <[email protected]>
Co-authored-by: Denis Ledoux <[email protected]>
---
 Lib/email/_header_value_parser.py                                        |   
15 ++++++
 Lib/test/test_email/test__header_value_parser.py                         |   
23 ++++++++++
 Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst |    
6 ++
 3 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst

Index: Python-3.12.12/Lib/email/_header_value_parser.py
===================================================================
--- Python-3.12.12.orig/Lib/email/_header_value_parser.py       2026-02-06 
00:08:35.667684507 +0100
+++ Python-3.12.12/Lib/email/_header_value_parser.py    2026-02-06 
00:08:40.746286971 +0100
@@ -101,6 +101,12 @@
     return str(value).replace('\\', '\\\\').replace('"', '\\"')
 
 
+def make_parenthesis_pairs(value):
+    """Escape parenthesis and backslash for use within a comment."""
+    return str(value).replace('\\', '\\\\') \
+        .replace('(', '\\(').replace(')', '\\)')
+
+
 def quote_string(value):
     escaped = make_quoted_pairs(value)
     return f'"{escaped}"'
@@ -933,7 +939,7 @@
         return ' '
 
     def startswith_fws(self):
-        return True
+        return self and self[0] in WSP
 
 
 class ValueTerminal(Terminal):
@@ -2922,6 +2928,13 @@
                     [ValueTerminal(make_quoted_pairs(p), 'ptext')
                      for p in newparts] +
                     [ValueTerminal('"', 'ptext')])
+            if part.token_type == 'comment':
+                newparts = (
+                    [ValueTerminal('(', 'ptext')] +
+                    [ValueTerminal(make_parenthesis_pairs(p), 'ptext')
+                     if p.token_type == 'ptext' else p
+                     for p in newparts] +
+                    [ValueTerminal(')', 'ptext')])
             if not part.as_ew_allowed:
                 wrap_as_ew_blocked += 1
                 newparts.append(end_ew_not_allowed)
Index: Python-3.12.12/Lib/test/test_email/test__header_value_parser.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_email/test__header_value_parser.py        
2026-02-06 00:08:37.343959625 +0100
+++ Python-3.12.12/Lib/test/test_email/test__header_value_parser.py     
2026-02-06 00:08:40.747102748 +0100
@@ -3141,6 +3141,29 @@
             with self.subTest(to=to):
                 self._test(parser.get_address_list(to)[0], folded, 
policy=policy)
 
+    def test_address_list_with_long_unwrapable_comment(self):
+        policy = self.policy.clone(max_line_length=40)
+        cases = [
+            # (to, folded)
+            ('(loremipsumdolorsitametconsecteturadipi)<[email protected]>',
+             '(loremipsumdolorsitametconsecteturadipi)<[email protected]>\n'),
+            ('<[email protected]>(loremipsumdolorsitametconsecteturadipi)',
+             '<[email protected]>(loremipsumdolorsitametconsecteturadipi)\n'),
+            ('(loremipsum dolorsitametconsecteturadipi)<[email protected]>',
+             '(loremipsum dolorsitametconsecteturadipi)<[email protected]>\n'),
+             ('<[email protected]>(loremipsum dolorsitametconsecteturadipi)',
+             '<[email protected]>(loremipsum\n 
dolorsitametconsecteturadipi)\n'),
+            ('(Escaped \\( \\) chars \\\\ in comments stay 
escaped)<[email protected]>',
+             '(Escaped \\( \\) chars \\\\ in comments stay\n 
escaped)<[email protected]>\n'),
+            
('((loremipsum)(loremipsum)(loremipsum)(loremipsum))<[email protected]>',
+             
'((loremipsum)(loremipsum)(loremipsum)(loremipsum))<[email protected]>\n'),
+            ('((loremipsum)(loremipsum)(loremipsum) 
(loremipsum))<[email protected]>',
+             '((loremipsum)(loremipsum)(loremipsum)\n 
(loremipsum))<[email protected]>\n'),
+        ]
+        for (to, folded) in cases:
+            with self.subTest(to=to):
+                self._test(parser.get_address_list(to)[0], folded, 
policy=policy)
+
     # XXX Need tests with comments on various sides of a unicode token,
     # and with unicode tokens in the comments.  Spaces inside the quotes
     # currently don't do the right thing.
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
     2026-02-06 00:08:40.747576711 +0100
@@ -0,0 +1,6 @@
+Fixed a bug in the folding of comments when flattening an email message
+using a modern email policy. Comments consisting of a very long sequence of
+non-foldable characters could trigger a forced line wrap that omitted the
+required leading space on the continuation line, causing the remainder of
+the comment to be interpreted as a new header field. This enabled header
+injection with carefully crafted inputs.

++++++ CVE-2025-12781-b64decode-alt-chars.patch ++++++
>From f922c02c529d25d61aa9c28a8192639c1fce8d4d Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <[email protected]>
Date: Wed, 5 Nov 2025 20:12:31 +0200
Subject: [PATCH] gh-125346: Add more base64 tests

Add more tests for the altchars argument of b64decode() and for the map01
argument of b32decode().
---
 Doc/library/base64.rst                                                  |   18 
+++-
 Lib/base64.py                                                           |   40 
++++++++-
 Lib/test/test_base64.py                                                 |   42 
+++++++++-
 Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst |    5 
+
 4 files changed, 91 insertions(+), 14 deletions(-)

Index: Python-3.12.12/Doc/library/base64.rst
===================================================================
--- Python-3.12.12.orig/Doc/library/base64.rst  2025-10-09 13:07:00.000000000 
+0200
+++ Python-3.12.12/Doc/library/base64.rst       2026-02-10 22:15:41.801235355 
+0100
@@ -74,15 +74,20 @@
    A :exc:`binascii.Error` exception is raised
    if *s* is incorrectly padded.
 
-   If *validate* is ``False`` (the default), characters that are neither
+   If *validate* is false (the default), characters that are neither
    in the normal base-64 alphabet nor the alternative alphabet are
-   discarded prior to the padding check.  If *validate* is ``True``,
-   these non-alphabet characters in the input result in a
-   :exc:`binascii.Error`.
+   discarded prior to the padding check, but the ``+`` and ``/`` characters
+   keep their meaning if they are not in *altchars* (they will be discarded
+   in future Python versions).
+   If *validate* is true, these non-alphabet characters in the input
+   result in a :exc:`binascii.Error`.
 
    For more information about the strict base64 check, see 
:func:`binascii.a2b_base64`
 
-   May assert or raise a :exc:`ValueError` if the length of *altchars* is not 
2.
+   .. deprecated:: next
+      Accepting the ``+`` and ``/`` characters with an alternative alphabet
+      is now deprecated.
+
 
 .. function:: standard_b64encode(s)
 
@@ -113,6 +118,9 @@
    ``/`` in the standard Base64 alphabet, and return the decoded
    :class:`bytes`.
 
+   .. deprecated:: next
+      Accepting the ``+`` and ``/`` characters is now deprecated.
+
 
 .. function:: b32encode(s)
 
Index: Python-3.12.12/Lib/base64.py
===================================================================
--- Python-3.12.12.orig/Lib/base64.py   2026-02-10 22:15:02.534016402 +0100
+++ Python-3.12.12/Lib/base64.py        2026-02-10 22:15:41.801591556 +0100
@@ -71,20 +71,39 @@
     The result is returned as a bytes object.  A binascii.Error is raised if
     s is incorrectly padded.
 
-    If validate is False (the default), characters that are neither in the
+    If validate is false (the default), characters that are neither in the
     normal base-64 alphabet nor the alternative alphabet are discarded prior
-    to the padding check.  If validate is True, these non-alphabet characters
+    to the padding check.  If validate is true, these non-alphabet characters
     in the input result in a binascii.Error.
     For more information about the strict base64 check, see:
 
     https://docs.python.org/3.11/library/binascii.html#binascii.a2b_base64
     """
     s = _bytes_from_decode_data(s)
+    badchar = None
     if altchars is not None:
         altchars = _bytes_from_decode_data(altchars)
-        assert len(altchars) == 2, repr(altchars)
+        if len(altchars) != 2:
+            raise ValueError(f'invalid altchars: {altchars!r}')
+        for b in b'+/':
+            if b not in altchars and b in s:
+                badchar = b
+                break
         s = s.translate(bytes.maketrans(altchars, b'+/'))
-    return binascii.a2b_base64(s, strict_mode=validate)
+    result = binascii.a2b_base64(s, strict_mode=validate)
+    if badchar is not None:
+        import warnings
+        if validate:
+            warnings.warn(f'invalid character {chr(badchar)!a} in Base64 data '
+                          f'with altchars={altchars!r} and validate=True '
+                          f'will be an error in future Python versions',
+                          DeprecationWarning, stacklevel=2)
+        else:
+            warnings.warn(f'invalid character {chr(badchar)!a} in Base64 data '
+                          f'with altchars={altchars!r} and validate=False '
+                          f'will be discarded in future Python versions',
+                          FutureWarning, stacklevel=2)
+    return result
 
 
 def standard_b64encode(s):
@@ -129,8 +148,19 @@
     The alphabet uses '-' instead of '+' and '_' instead of '/'.
     """
     s = _bytes_from_decode_data(s)
+    badchar = None
+    for b in b'+/':
+        if b in s:
+            badchar = b
+            break
     s = s.translate(_urlsafe_decode_translation)
-    return b64decode(s)
+    result = binascii.a2b_base64(s, strict_mode=False)
+    if badchar is not None:
+        import warnings
+        warnings.warn(f'invalid character {chr(badchar)!a} in URL-safe Base64 
data '
+                      f'will be discarded in future Python versions',
+                      FutureWarning, stacklevel=2)
+    return result
 
 
 
Index: Python-3.12.12/Lib/test/test_base64.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_base64.py 2026-02-10 22:15:04.364274059 
+0100
+++ Python-3.12.12/Lib/test/test_base64.py      2026-02-10 22:17:42.445725550 
+0100
@@ -232,6 +232,25 @@
                                b'\xd3V\xbeo\xf7\x1d')
         self.check_decode_type_errors(base64.urlsafe_b64decode)
 
+    def test_b64decode_altchars(self):
+        # Test with arbitrary alternative characters
+        eq = self.assertEqual
+        res = b'\xd3V\xbeo\xf7\x1d'
+        for altchars in b'*$', b'+/', b'/+', b'+_', b'-+', b'-/', b'/_':
+            data = b'01a%cb%ccd' % tuple(altchars)
+            data_str = data.decode('ascii')
+            altchars_str = altchars.decode('ascii')
+
+            eq(base64.b64decode(data, altchars=altchars), res)
+            eq(base64.b64decode(data_str, altchars=altchars), res)
+            eq(base64.b64decode(data, altchars=altchars_str), res)
+            eq(base64.b64decode(data_str, altchars=altchars_str), res)
+
+        self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+')
+        self.assertRaises(ValueError, base64.b64decode, b'', altchars=b'+/-')
+        self.assertRaises(ValueError, base64.b64decode, '', altchars='+')
+        self.assertRaises(ValueError, base64.b64decode, '', altchars='+/-')
+
     def test_b64decode_padding_error(self):
         self.assertRaises(binascii.Error, base64.b64decode, b'abc')
         self.assertRaises(binascii.Error, base64.b64decode, 'abc')
@@ -263,10 +282,25 @@
             with self.assertRaises(binascii.Error):
                 base64.b64decode(bstr.decode('ascii'), validate=True)
 
-        # Normal alphabet characters not discarded when alternative given
-        res = b'\xFB\xEF\xBE\xFF\xFF\xFF'
-        self.assertEqual(base64.b64decode(b'++[[//]]', b'[]'), res)
-        self.assertEqual(base64.urlsafe_b64decode(b'++--//__'), res)
+        # Normal alphabet characters will be discarded when alternative given
+        with self.assertWarns(FutureWarning):
+            self.assertEqual(base64.b64decode(b'++++', altchars=b'-_'),
+                             b'\xfb\xef\xbe')
+        with self.assertWarns(FutureWarning):
+            self.assertEqual(base64.b64decode(b'////', altchars=b'-_'),
+                             b'\xff\xff\xff')
+        with self.assertWarns(DeprecationWarning):
+            self.assertEqual(base64.b64decode(b'++++', altchars=b'-_', 
validate=True),
+                             b'\xfb\xef\xbe')
+        with self.assertWarns(DeprecationWarning):
+            self.assertEqual(base64.b64decode(b'////', altchars=b'-_', 
validate=True),
+                             b'\xff\xff\xff')
+        with self.assertWarns(FutureWarning):
+            self.assertEqual(base64.urlsafe_b64decode(b'++++'), 
b'\xfb\xef\xbe')
+        with self.assertWarns(FutureWarning):
+            self.assertEqual(base64.urlsafe_b64decode(b'////'), 
b'\xff\xff\xff')
+        with self.assertRaises(binascii.Error):
+            base64.b64decode(b'+/!', altchars=b'-_')
 
     def test_b32encode(self):
         eq = self.assertEqual
Index: 
Python-3.12.12/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Library/2025-11-06-12-03-29.gh-issue-125346.7Gfpgw.rst
      2026-02-10 22:15:41.802353823 +0100
@@ -0,0 +1,5 @@
+Accepting ``+`` and ``/`` characters with an alternative alphabet in
+:func:`base64.b64decode` and :func:`base64.urlsafe_b64decode` is now
+deprecated.
+In future Python versions they will be errors in the strict mode and
+discarded in the non-strict mode.

++++++ CVE-2025-15282-urllib-ctrl-chars.patch ++++++
>From f336af1c4b103297de1322bbe00f920f3e58b899 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Tue, 20 Jan 2026 14:45:58 -0600
Subject: [PATCH 1/2] [3.12] gh-143925: Reject control characters in data: URL
 mediatypes (cherry picked from commit
 f25509e78e8be6ea73c811ac2b8c928c28841b9f) (cherry picked from commit
 2c9c746077d8119b5bcf5142316992e464594946)

Co-authored-by: Seth Michael Larson <[email protected]>
---
 Lib/test/test_urllib.py                                                  |    
8 ++++++++
 Lib/urllib/request.py                                                    |    
5 +++++
 Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst |    
1 +
 3 files changed, 14 insertions(+)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst

Index: Python-3.12.12/Lib/test/test_urllib.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_urllib.py 2026-02-10 22:15:06.355594386 
+0100
+++ Python-3.12.12/Lib/test/test_urllib.py      2026-02-10 22:18:23.820760279 
+0100
@@ -12,6 +12,7 @@
 from test.support import os_helper
 from test.support import socket_helper
 from test.support import warnings_helper
+from test.support import control_characters_c0
 import os
 try:
     import ssl
@@ -688,6 +689,13 @@
         # missing padding character
         self.assertRaises(ValueError,urllib.request.urlopen,'data:;base64,Cg=')
 
+    def test_invalid_mediatype(self):
+        for c0 in control_characters_c0():
+            self.assertRaises(ValueError,urllib.request.urlopen,
+                              f'data:text/html;{c0},data')
+        for c0 in control_characters_c0():
+            self.assertRaises(ValueError,urllib.request.urlopen,
+                              f'data:text/html{c0};base64,ZGF0YQ==')
 
 class urlretrieve_FileTests(unittest.TestCase):
     """Test urllib.urlretrieve() on local files"""
Index: Python-3.12.12/Lib/urllib/request.py
===================================================================
--- Python-3.12.12.orig/Lib/urllib/request.py   2026-02-10 22:15:06.739534061 
+0100
+++ Python-3.12.12/Lib/urllib/request.py        2026-02-10 22:18:23.819325524 
+0100
@@ -1655,6 +1655,11 @@
         scheme, data = url.split(":",1)
         mediatype, data = data.split(",",1)
 
+        # Disallow control characters within mediatype.
+        if re.search(r"[\x00-\x1F\x7F]", mediatype):
+            raise ValueError(
+                "Control characters not allowed in data: mediatype")
+
         # even base64 encoded data URLs might be quoted so unquote in any case:
         data = unquote_to_bytes(data)
         if mediatype.endswith(";base64"):
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-51-19.gh-issue-143925.mrtcHW.rst
     2026-02-10 22:18:23.819830797 +0100
@@ -0,0 +1 @@
+Reject control characters in ``data:`` URL media types.

++++++ CVE-2025-15366-imap-ctrl-chars.patch ++++++
>From 7485ee5e2cf81d3e5ad0d9c3be73cecd2ab4eec7 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Fri, 16 Jan 2026 10:54:09 -0600
Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters

---
 Lib/imaplib.py                                                           |    
4 +++-
 Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst |    
1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

Index: Python-3.12.12/Lib/imaplib.py
===================================================================
--- Python-3.12.12.orig/Lib/imaplib.py  2026-02-10 22:15:03.417592955 +0100
+++ Python-3.12.12/Lib/imaplib.py       2026-02-10 22:18:02.094605035 +0100
@@ -132,7 +132,7 @@
 # We compile these in _mode_xxx.
 _Literal = br'.*{(?P<size>\d+)}$'
 _Untagged_status = br'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?'
-
+_control_chars = re.compile(b'[\x00-\x1F\x7F]')
 
 
 class IMAP4:
@@ -994,6 +994,8 @@
             if arg is None: continue
             if isinstance(arg, str):
                 arg = bytes(arg, self._encoding)
+            if _control_chars.search(arg):
+                raise ValueError("Control characters not allowed in commands")
             data = data + b' ' + arg
 
         literal = self.literal
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst
     2026-02-10 22:18:02.095167966 +0100
@@ -0,0 +1 @@
+Reject control characters in IMAP commands.

++++++ CVE-2025-15367-poplib-ctrl-chars.patch ++++++
>From b6f733b285b1c4f27dacb5c2e1f292c914e8b933 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Fri, 16 Jan 2026 10:54:09 -0600
Subject: [PATCH 1/2] Add 'test.support' fixture for C0 control characters

---
 Lib/poplib.py                                                            |    
2 ++
 Lib/test/test_poplib.py                                                  |    
8 ++++++++
 Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst |    
1 +
 3 files changed, 11 insertions(+)

Index: Python-3.12.12/Lib/poplib.py
===================================================================
--- Python-3.12.12.orig/Lib/poplib.py   2026-02-11 23:46:29.442215955 +0100
+++ Python-3.12.12/Lib/poplib.py        2026-02-11 23:46:46.713251058 +0100
@@ -122,6 +122,8 @@
     def _putcmd(self, line):
         if self._debugging: print('*cmd*', repr(line))
         line = bytes(line, self.encoding)
+        if re.search(b'[\x00-\x1F\x7F]', line):
+            raise ValueError('Control characters not allowed in commands')
         self._putline(line)
 
 
Index: Python-3.12.12/Lib/test/test_poplib.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_poplib.py 2026-02-11 23:46:31.636412813 
+0100
+++ Python-3.12.12/Lib/test/test_poplib.py      2026-02-11 23:46:46.713442229 
+0100
@@ -17,6 +17,7 @@
 from test.support import threading_helper
 from test.support import asynchat
 from test.support import asyncore
+from test.support import control_characters_c0
 
 
 test_support.requires_working_socket(module=True)
@@ -395,6 +396,13 @@
         self.assertIsNone(self.client.sock)
         self.assertIsNone(self.client.file)
 
+    def test_control_characters(self):
+        for c0 in control_characters_c0():
+            with self.assertRaises(ValueError):
+                self.client.user(f'user{c0}')
+            with self.assertRaises(ValueError):
+                self.client.pass_(f'{c0}pass')
+
     @requires_ssl
     def test_stls_capa(self):
         capa = self.client.capa()
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst
     2026-02-11 23:46:46.713620996 +0100
@@ -0,0 +1 @@
+Reject control characters in POP3 commands.

++++++ CVE-2026-0672-http-hdr-inject-cookie-Morsel.patch ++++++
>From 9729bdf210967c806f3364c76663fc2ade58e389 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <[email protected]>
Date: Tue, 20 Jan 2026 15:23:42 -0600
Subject: [PATCH] gh-143919: Reject control characters in http cookies (cherry
 picked from commit 95746b3a13a985787ef53b977129041971ed7f70)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Seth Michael Larson <[email protected]>
Co-authored-by: Bartosz Sławecki <[email protected]>
Co-authored-by: sobolevn <[email protected]>
---
 Doc/library/http.cookies.rst                                             |    
4 
 Lib/http/cookies.py                                                      |   
25 ++++
 Lib/test/test_http_cookies.py                                            |   
52 +++++++++-
 Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst |    
1 
 4 files changed, 73 insertions(+), 9 deletions(-)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst

Index: Python-3.12.12/Doc/library/http.cookies.rst
===================================================================
--- Python-3.12.12.orig/Doc/library/http.cookies.rst    2025-10-09 
13:07:00.000000000 +0200
+++ Python-3.12.12/Doc/library/http.cookies.rst 2026-02-10 22:17:53.970413039 
+0100
@@ -272,9 +272,9 @@
    Set-Cookie: chips=ahoy
    Set-Cookie: vienna=finger
    >>> C = cookies.SimpleCookie()
-   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
+   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=;";')
    >>> print(C)
-   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
+   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;"
    >>> C = cookies.SimpleCookie()
    >>> C["oreo"] = "doublestuff"
    >>> C["oreo"]["path"] = "/"
Index: Python-3.12.12/Lib/http/cookies.py
===================================================================
--- Python-3.12.12.orig/Lib/http/cookies.py     2026-02-10 22:15:03.102916960 
+0100
+++ Python-3.12.12/Lib/http/cookies.py  2026-02-10 22:17:53.970584713 +0100
@@ -87,9 +87,9 @@
 such trickeries do not confuse it.
 
    >>> C = cookies.SimpleCookie()
-   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
+   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=;";')
    >>> print(C)
-   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
+   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;"
 
 Each element of the Cookie also supports all of the RFC 2109
 Cookie attributes.  Here's an example which sets the Path
@@ -170,6 +170,15 @@
 })
 
 _is_legal_key = re.compile('[%s]+' % re.escape(_LegalChars)).fullmatch
+_control_character_re = re.compile(r'[\x00-\x1F\x7F]')
+
+
+def _has_control_character(*val):
+    """Detects control characters within a value.
+    Supports any type, as header values can be any type.
+    """
+    return any(_control_character_re.search(str(v)) for v in val)
+
 
 def _quote(str):
     r"""Quote a string for use in a cookie header.
@@ -292,12 +301,16 @@
         K = K.lower()
         if not K in self._reserved:
             raise CookieError("Invalid attribute %r" % (K,))
+        if _has_control_character(K, V):
+            raise CookieError(f"Control characters are not allowed in cookies 
{K!r} {V!r}")
         dict.__setitem__(self, K, V)
 
     def setdefault(self, key, val=None):
         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 cookies 
%r %r" % (key, val,))
         return dict.setdefault(self, key, val)
 
     def __eq__(self, morsel):
@@ -333,6 +346,9 @@
             raise CookieError('Attempt to set a reserved key %r' % (key,))
         if not _is_legal_key(key):
             raise CookieError('Illegal key %r' % (key,))
+        if _has_control_character(key, val, coded_val):
+            raise CookieError(
+                "Control characters are not allowed in cookies %r %r %r" % 
(key, val, coded_val,))
 
         # It's a good key, so save it.
         self._key = key
@@ -486,7 +502,10 @@
         result = []
         items = sorted(self.items())
         for key, value in items:
-            result.append(value.output(attrs, header))
+            value_output = value.output(attrs, header)
+            if _has_control_character(value_output):
+                raise CookieError("Control characters are not allowed in 
cookies")
+            result.append(value_output)
         return sep.join(result)
 
     __str__ = output
Index: Python-3.12.12/Lib/test/test_http_cookies.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_http_cookies.py   2026-02-10 
22:15:05.120676729 +0100
+++ Python-3.12.12/Lib/test/test_http_cookies.py        2026-02-10 
22:17:53.970780833 +0100
@@ -17,10 +17,10 @@
              'repr': "<SimpleCookie: chips='ahoy' vienna='finger'>",
              'output': 'Set-Cookie: chips=ahoy\nSet-Cookie: vienna=finger'},
 
-            {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"',
-             'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=\012;'},
-             'repr': '''<SimpleCookie: keebler='E=mc2; L="Loves"; 
fudge=\\n;'>''',
-             'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; 
fudge=\\012;"'},
+            {'data': 'keebler="E=mc2; L=\\"Loves\\"; fudge=;"',
+             'dict': {'keebler' : 'E=mc2; L="Loves"; fudge=;'},
+             'repr': '''<SimpleCookie: keebler='E=mc2; L="Loves"; fudge=;'>''',
+             'output': 'Set-Cookie: keebler="E=mc2; L=\\"Loves\\"; fudge=;"'},
 
             # Check illegal cookies that have an '=' char in an unquoted value
             {'data': 'keebler=E=mc2',
@@ -563,6 +563,50 @@
                 r'Set-Cookie: key=coded_val; '
                 r'expires=\w+, \d+ \w+ \d+ \d+:\d+:\d+ \w+')
 
+    def test_control_characters(self):
+        for c0 in support.control_characters_c0():
+            morsel = cookies.Morsel()
+
+            # .__setitem__()
+            with self.assertRaises(cookies.CookieError):
+                morsel[c0] = "val"
+            with self.assertRaises(cookies.CookieError):
+                morsel["path"] = c0
+
+            # .setdefault()
+            with self.assertRaises(cookies.CookieError):
+                morsel.setdefault("path", c0)
+            with self.assertRaises(cookies.CookieError):
+                morsel.setdefault(c0, "val")
+
+            # .set()
+            with self.assertRaises(cookies.CookieError):
+                morsel.set(c0, "val", "coded-value")
+            with self.assertRaises(cookies.CookieError):
+                morsel.set("path", c0, "coded-value")
+            with self.assertRaises(cookies.CookieError):
+                morsel.set("path", "val", c0)
+
+    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.
+        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.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.output()
+
 
 def load_tests(loader, tests, pattern):
     tests.addTest(doctest.DocTestSuite(cookies))
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-13-15.gh-issue-143919.kchwZV.rst
     2026-02-10 22:17:53.970970320 +0100
@@ -0,0 +1 @@
+Reject control characters in :class:`http.cookies.Morsel` fields and values.

++++++ CVE-2026-0865-wsgiref-ctrl-chars.patch ++++++
>From 03a7342c9e2bbdab20a6d882bf334608dc7a5d4b Mon Sep 17 00:00:00 2001
From: "Gregory P. Smith" <[email protected]>
Date: Sat, 17 Jan 2026 10:23:57 -0800
Subject: [PATCH] [3.12] gh-143916: Reject control characters in
 wsgiref.headers.Headers (GH-143917) (GH-143973)

gh-143916: Reject control characters in wsgiref.headers.Headers  (GH-143917)

* Add 'test.support' fixture for C0 control characters
* gh-143916: Reject control characters in wsgiref.headers.Headers

(cherry picked from commit f7fceed79ca1bceae8dbe5ba5bc8928564da7211)
(cherry picked from commit 22e4d55285cee52bc4dbe061324e5f30bd4dee58)

Co-authored-by: Gregory P. Smith <[email protected]>
Co-authored-by: Seth Michael Larson <[email protected]>
---
 Lib/test/support/__init__.py                                             |    
7 +++++
 Lib/test/test_wsgiref.py                                                 |   
12 +++++++++-
 Lib/wsgiref/headers.py                                                   |    
3 ++
 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst |    
2 +
 4 files changed, 23 insertions(+), 1 deletion(-)
 create mode 100644 
Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst

Index: Python-3.12.12/Lib/test/support/__init__.py
===================================================================
--- Python-3.12.12.orig/Lib/test/support/__init__.py    2026-02-10 
22:15:04.163026806 +0100
+++ Python-3.12.12/Lib/test/support/__init__.py 2026-02-10 22:17:57.451276662 
+0100
@@ -2591,3 +2591,10 @@
         if self.iter_raises:
             1/0
         return self
+
+
+def control_characters_c0() -> list[str]:
+    """Returns a list of C0 control characters as strings.
+    C0 control characters defined as the byte range 0x00-0x1F, and 0x7F.
+    """
+    return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"]
Index: Python-3.12.12/Lib/test/test_wsgiref.py
===================================================================
--- Python-3.12.12.orig/Lib/test/test_wsgiref.py        2026-02-10 
22:15:06.432657502 +0100
+++ Python-3.12.12/Lib/test/test_wsgiref.py     2026-02-10 22:17:57.451566378 
+0100
@@ -1,6 +1,6 @@
 from unittest import mock
 from test import support
-from test.support import socket_helper
+from test.support import socket_helper, control_characters_c0
 from test.test_httpservers import NoLogRequestHandler
 from unittest import TestCase
 from wsgiref.util import setup_testing_defaults
@@ -503,6 +503,16 @@
             '\r\n'
         )
 
+    def testRaisesControlCharacters(self):
+        headers = Headers()
+        for c0 in control_characters_c0():
+            self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", 
"val")
+            self.assertRaises(ValueError, headers.__setitem__, "key", 
f"val{c0}")
+            self.assertRaises(ValueError, headers.add_header, f"key{c0}", 
"val", param="param")
+            self.assertRaises(ValueError, headers.add_header, "key", 
f"val{c0}", param="param")
+            self.assertRaises(ValueError, headers.add_header, "key", "val", 
param=f"param{c0}")
+
+
 class ErrorHandler(BaseCGIHandler):
     """Simple handler subclass for testing BaseHandler"""
 
Index: Python-3.12.12/Lib/wsgiref/headers.py
===================================================================
--- Python-3.12.12.orig/Lib/wsgiref/headers.py  2026-02-10 22:15:06.773169140 
+0100
+++ Python-3.12.12/Lib/wsgiref/headers.py       2026-02-10 22:17:57.451729575 
+0100
@@ -9,6 +9,7 @@
 # existence of which force quoting of the parameter value.
 import re
 tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
+_control_chars_re = re.compile(r'[\x00-\x1F\x7F]')
 
 def _formatparam(param, value=None, quote=1):
     """Convenience function to format and return a key=value pair.
@@ -41,6 +42,8 @@
     def _convert_string_type(self, value):
         """Convert/check value type."""
         if type(value) is str:
+            if _control_chars_re.search(value):
+                raise ValueError("Control characters not allowed in headers")
             return value
         raise AssertionError("Header names/values must be"
             " of type str (got {0})".format(repr(value)))
Index: 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 
Python-3.12.12/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
     2026-02-10 22:17:57.451848490 +0100
@@ -0,0 +1,2 @@
+Reject C0 control characters within wsgiref.headers.Headers fields, values,
+and parameters.


++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.vwuuUW/_old  2026-02-18 17:05:21.881561081 +0100
+++ /var/tmp/diff_new_pack.vwuuUW/_new  2026-02-18 17:05:21.889561413 +0100
@@ -1,6 +1,6 @@
-mtime: 1766171591
-commit: 3ec5b189c8398b00c1828ce95bd81824ae2a9b8e0ba6d3653dd2b58d3b35352d
+mtime: 1770850038
+commit: 07beab470daf1bea6b0fbc6af7e3bd5f0a9f708806d74c128490c9fb47a3bd6d
 url: https://src.opensuse.org/python-interpreters/python312.git
-revision: 3ec5b189c8398b00c1828ce95bd81824ae2a9b8e0ba6d3653dd2b58d3b35352d
+revision: 07beab470daf1bea6b0fbc6af7e3bd5f0a9f708806d74c128490c9fb47a3bd6d
 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-02-11 23:47:34.000000000 +0100
@@ -0,0 +1,5 @@
+.osc
+*.obscpio
+_build.*
+.pbuild
+python312-3.12.*-build

Reply via email to