Update to 3.12.13

Security fixes for CVE-2025-6075, CVE-2025-13837, CVE-2025-15282, CVE-2025-59375, CVE-2026-0672

Related: RHEL-167886, RHEL-168120
This commit is contained in:
Tomáš Hrnčiar 2026-03-03 14:55:29 +01:00 committed by Charalampos Stratakis
parent 6349f8d8e9
commit eb6081b2bf
7 changed files with 10 additions and 539 deletions

View File

@ -84,7 +84,7 @@ index 0000000000..75d926ab59
+Fix the :mod:`ssl` module error handling of connection terminate by peer. +Fix the :mod:`ssl` module error handling of connection terminate by peer.
+It now throws an OSError with the appropriate error code instead of an EOFError. +It now throws an OSError with the appropriate error code instead of an EOFError.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 0b8cf0b6df..42a4c95890 100644 index aae4dc323d..27dd7bbe11 100644
--- a/Modules/_ssl.c --- a/Modules/_ssl.c
+++ b/Modules/_ssl.c +++ b/Modules/_ssl.c
@@ -573,7 +573,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) { @@ -573,7 +573,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) {

View File

@ -1,139 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 22 Dec 2025 14:48:49 +0100
Subject: 00471: CVE-2025-12084
* gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146)
* gh-142754: Ensure that Element & Attr instances have the ownerDocument attribute (GH-142794)
(cherry picked from commit 1cc7551b3f9f71efbc88d96dce90f82de98b2454)
(cherry picked from commit 08d8e18ad81cd45bc4a27d6da478b51ea49486e4)
(cherry picked from commit 8d2d7bb2e754f8649a68ce4116271a4932f76907)
Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com>
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
---
Lib/test/test_minidom.py | 33 ++++++++++++++++++-
Lib/xml/dom/minidom.py | 11 ++-----
...-12-01-09-36-45.gh-issue-142145.tcAUhg.rst | 6 ++++
3 files changed, 41 insertions(+), 9 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
index 699265ccad..ab4823c831 100644
--- a/Lib/test/test_minidom.py
+++ b/Lib/test/test_minidom.py
@@ -2,13 +2,14 @@
import copy
import pickle
+import time
import io
from test import support
import unittest
import xml.dom.minidom
-from xml.dom.minidom import parse, Attr, Node, Document, parseString
+from xml.dom.minidom import parse, Attr, Node, Document, Element, parseString
from xml.dom.minidom import getDOMImplementation
from xml.parsers.expat import ExpatError
@@ -176,6 +177,36 @@ def testAppendChild(self):
self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
dom.unlink()
+ @support.requires_resource('cpu')
+ def testAppendChildNoQuadraticComplexity(self):
+ impl = getDOMImplementation()
+
+ newdoc = impl.createDocument(None, "some_tag", None)
+ top_element = newdoc.documentElement
+ children = [newdoc.createElement(f"child-{i}") for i in range(1, 2 ** 15 + 1)]
+ element = top_element
+
+ start = time.monotonic()
+ for child in children:
+ element.appendChild(child)
+ element = child
+ end = time.monotonic()
+
+ # This example used to take at least 30 seconds.
+ # Conservative assertion due to the wide variety of systems and
+ # build configs timing based tests wind up run under.
+ # A --with-address-sanitizer --with-pydebug build on a rpi5 still
+ # completes this loop in <0.5 seconds.
+ self.assertLess(end - start, 4)
+
+ def testSetAttributeNodeWithoutOwnerDocument(self):
+ # regression test for gh-142754
+ elem = Element("test")
+ attr = Attr("id")
+ attr.value = "test-id"
+ elem.setAttributeNode(attr)
+ self.assertEqual(elem.getAttribute("id"), "test-id")
+
def testAppendChildFragment(self):
dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
dom.documentElement.appendChild(frag)
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
index ef8a159833..cada981f39 100644
--- a/Lib/xml/dom/minidom.py
+++ b/Lib/xml/dom/minidom.py
@@ -292,13 +292,6 @@ def _append_child(self, node):
childNodes.append(node)
node.parentNode = self
-def _in_document(node):
- # return True iff node is part of a document tree
- while node is not None:
- if node.nodeType == Node.DOCUMENT_NODE:
- return True
- node = node.parentNode
- return False
def _write_data(writer, data):
"Writes datachars to writer."
@@ -355,6 +348,7 @@ class Attr(Node):
def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
prefix=None):
self.ownerElement = None
+ self.ownerDocument = None
self._name = qName
self.namespaceURI = namespaceURI
self._prefix = prefix
@@ -680,6 +674,7 @@ class Element(Node):
def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
localName=None):
+ self.ownerDocument = None
self.parentNode = None
self.tagName = self.nodeName = tagName
self.prefix = prefix
@@ -1539,7 +1534,7 @@ def _clear_id_cache(node):
if node.nodeType == Node.DOCUMENT_NODE:
node._id_cache.clear()
node._id_search_stack = None
- elif _in_document(node):
+ elif node.ownerDocument:
node.ownerDocument._id_cache.clear()
node.ownerDocument._id_search_stack= None
diff --git a/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst
new file mode 100644
index 0000000000..05c7df35d1
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst
@@ -0,0 +1,6 @@
+Remove quadratic behavior in ``xml.minidom`` node ID cache clearing. In order
+to do this without breaking existing users, we also add the *ownerDocument*
+attribute to :mod:`xml.dom.minidom` elements and attributes created by directly
+instantiating the ``Element`` or ``Attr`` class. Note that this way of creating
+nodes is not supported; creator functions like
+:py:meth:`xml.dom.Document.documentElement` should be used instead.

View File

@ -1,159 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 22 Dec 2025 14:50:18 +0100
Subject: 00472: CVE-2025-13836
[3.12] gh-119451: Fix a potential denial of service in http.client (GH-119454) (#142140)
gh-119451: Fix a potential denial of service in http.client (GH-119454)
Reading the whole body of the HTTP response could cause OOM if
the Content-Length value is too large even if the server does not send
a large amount of data. Now the HTTP client reads large data by chunks,
therefore the amount of consumed memory is proportional to the amount
of sent data.
(cherry picked from commit 5a4c4a033a4a54481be6870aa1896fad732555b5)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
---
Lib/http/client.py | 28 ++++++--
Lib/test/test_httplib.py | 66 +++++++++++++++++++
...-05-23-11-47-48.gh-issue-119451.qkJe9-.rst | 5 ++
3 files changed, 95 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
diff --git a/Lib/http/client.py b/Lib/http/client.py
index fb29923d94..70451d67d4 100644
--- a/Lib/http/client.py
+++ b/Lib/http/client.py
@@ -111,6 +111,11 @@
_MAXLINE = 65536
_MAXHEADERS = 100
+# Data larger than this will be read in chunks, to prevent extreme
+# overallocation.
+_MIN_READ_BUF_SIZE = 1 << 20
+
+
# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2)
#
# VCHAR = %x21-7E
@@ -639,10 +644,25 @@ def _safe_read(self, amt):
reading. If the bytes are truly not available (due to EOF), then the
IncompleteRead exception can be used to detect the problem.
"""
- data = self.fp.read(amt)
- if len(data) < amt:
- raise IncompleteRead(data, amt-len(data))
- return data
+ cursize = min(amt, _MIN_READ_BUF_SIZE)
+ data = self.fp.read(cursize)
+ if len(data) >= amt:
+ return data
+ if len(data) < cursize:
+ raise IncompleteRead(data, amt - len(data))
+
+ data = io.BytesIO(data)
+ data.seek(0, 2)
+ while True:
+ # This is a geometric increase in read size (never more than
+ # doubling out the current length of data per loop iteration).
+ delta = min(cursize, amt - cursize)
+ data.write(self.fp.read(delta))
+ if data.tell() >= amt:
+ return data.getvalue()
+ cursize += delta
+ if data.tell() < cursize:
+ raise IncompleteRead(data.getvalue(), amt - data.tell())
def _safe_readinto(self, b):
"""Same as _safe_read, but for reading into a buffer."""
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 01f5a10190..e46dac0077 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -1452,6 +1452,72 @@ def run_server():
thread.join()
self.assertEqual(result, b"proxied data\n")
+ def test_large_content_length(self):
+ serv = socket.create_server((HOST, 0))
+ self.addCleanup(serv.close)
+
+ def run_server():
+ [conn, address] = serv.accept()
+ with conn:
+ while conn.recv(1024):
+ conn.sendall(
+ b"HTTP/1.1 200 Ok\r\n"
+ b"Content-Length: %d\r\n"
+ b"\r\n" % size)
+ conn.sendall(b'A' * (size//3))
+ conn.sendall(b'B' * (size - size//3))
+
+ thread = threading.Thread(target=run_server)
+ thread.start()
+ self.addCleanup(thread.join, 1.0)
+
+ conn = client.HTTPConnection(*serv.getsockname())
+ try:
+ for w in range(15, 27):
+ size = 1 << w
+ conn.request("GET", "/")
+ with conn.getresponse() as response:
+ self.assertEqual(len(response.read()), size)
+ finally:
+ conn.close()
+ thread.join(1.0)
+
+ def test_large_content_length_truncated(self):
+ serv = socket.create_server((HOST, 0))
+ self.addCleanup(serv.close)
+
+ def run_server():
+ while True:
+ [conn, address] = serv.accept()
+ with conn:
+ conn.recv(1024)
+ if not size:
+ break
+ conn.sendall(
+ b"HTTP/1.1 200 Ok\r\n"
+ b"Content-Length: %d\r\n"
+ b"\r\n"
+ b"Text" % size)
+
+ thread = threading.Thread(target=run_server)
+ thread.start()
+ self.addCleanup(thread.join, 1.0)
+
+ conn = client.HTTPConnection(*serv.getsockname())
+ try:
+ for w in range(18, 65):
+ size = 1 << w
+ conn.request("GET", "/")
+ with conn.getresponse() as response:
+ self.assertRaises(client.IncompleteRead, response.read)
+ conn.close()
+ finally:
+ conn.close()
+ size = 0
+ conn.request("GET", "/")
+ conn.close()
+ thread.join(1.0)
+
def test_putrequest_override_domain_validation(self):
"""
It should be possible to override the default validation
diff --git a/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst b/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
new file mode 100644
index 0000000000..6d6f25cd2f
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
@@ -0,0 +1,5 @@
+Fix a potential memory denial of service in the :mod:`http.client` module.
+When connecting to a malicious server, it could cause
+an arbitrary amount of memory to be allocated.
+This could have led to symptoms including a :exc:`MemoryError`, swapping, out
+of memory (OOM) killed processes or containers, or even system crashes.

View File

@ -1,90 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <seth@python.org>
Date: Sat, 17 Jan 2026 11:46:21 -0600
Subject: 00473: CVE-2026-0865
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
---
Lib/test/support/__init__.py | 7 +++++++
Lib/test/test_wsgiref.py | 12 +++++++++++-
Lib/wsgiref/headers.py | 3 +++
.../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
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 4c42234ccc..26c0af4b13 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2599,3 +2599,10 @@ def __iter__(self):
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"]
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
index 9316d0ecbc..28e3656632 100644
--- a/Lib/test/test_wsgiref.py
+++ b/Lib/test/test_wsgiref.py
@@ -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 @@ def testExtras(self):
'\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"""
diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py
index fab851c5a4..fd98e85d75 100644
--- a/Lib/wsgiref/headers.py
+++ b/Lib/wsgiref/headers.py
@@ -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 __init__(self, headers=None):
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)))
diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
new file mode 100644
index 0000000000..44bd0b2705
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
@@ -0,0 +1,2 @@
+Reject C0 control characters within wsgiref.headers.Headers fields, values,
+and parameters.

View File

@ -1,110 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Fri, 13 Feb 2026 17:04:54 +0100
Subject: [PATCH] [3.12] gh-144125: email: verify headers are sound in
BytesGenerator
gh-144125: email: verify headers are sound in BytesGenerator
(cherry picked from commit 052e55e7d44718fe46cbba0ca995cb8fcc359413)
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Denis Ledoux <dle@odoo.com>
Co-authored-by: Denis Ledoux <5822488+beledouxdenis@users.noreply.github.com>
Co-authored-by: Petr Viktorin <302922+encukou@users.noreply.github.com>
Co-authored-by: Bas Bloemsaat <1586868+basbloemsaat@users.noreply.github.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
---
Lib/email/generator.py | 12 +++++++++++-
Lib/test/test_email/test_generator.py | 4 +++-
Lib/test/test_email/test_policy.py | 6 +++++-
.../2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst | 4 ++++
4 files changed, 23 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
diff --git a/Lib/email/generator.py b/Lib/email/generator.py
index 47b9df8f4e6090..8cbc43ef5bc647 100644
--- a/Lib/email/generator.py
+++ b/Lib/email/generator.py
@@ -22,6 +22,7 @@
NLCRE = re.compile(r'\r\n|\r|\n')
fcre = re.compile(r'^From ', re.MULTILINE)
NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
+NEWLINE_WITHOUT_FWSP_BYTES = re.compile(br'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
class Generator:
@@ -429,7 +430,16 @@ def _write_headers(self, msg):
# This is almost the same as the string version, except for handling
# strings with 8bit bytes.
for h, v in msg.raw_items():
- self._fp.write(self.policy.fold_binary(h, v))
+ folded = self.policy.fold_binary(h, v)
+ if self.policy.verify_generated_headers:
+ linesep = self.policy.linesep.encode()
+ if not folded.endswith(linesep):
+ raise HeaderWriteError(
+ f'folded header does not end with {linesep!r}: {folded!r}')
+ if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)):
+ raise HeaderWriteError(
+ f'folded header contains newline: {folded!r}')
+ self._fp.write(folded)
# A blank line always separates headers from body
self.write(self._NL)
diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py
index c75a842c33578e..3ca79edf6a65d9 100644
--- a/Lib/test/test_email/test_generator.py
+++ b/Lib/test/test_email/test_generator.py
@@ -313,7 +313,7 @@ def test_flatten_unicode_linesep(self):
self.assertEqual(s.getvalue(), self.typ(expected))
def test_verify_generated_headers(self):
- """gh-121650: by default the generator prevents header injection"""
+ # gh-121650: by default the generator prevents header injection
class LiteralHeader(str):
name = 'Header'
def fold(self, **kwargs):
@@ -334,6 +334,8 @@ def fold(self, **kwargs):
with self.assertRaises(email.errors.HeaderWriteError):
message.as_string()
+ with self.assertRaises(email.errors.HeaderWriteError):
+ message.as_bytes()
class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py
index baa35fd68e49c5..71ec0febb0fd86 100644
--- a/Lib/test/test_email/test_policy.py
+++ b/Lib/test/test_email/test_policy.py
@@ -296,7 +296,7 @@ def test_short_maxlen_error(self):
policy.fold("Subject", subject)
def test_verify_generated_headers(self):
- """Turning protection off allows header injection"""
+ # Turning protection off allows header injection
policy = email.policy.default.clone(verify_generated_headers=False)
for text in (
'Header: Value\r\nBad: Injection\r\n',
@@ -319,6 +319,10 @@ def fold(self, **kwargs):
message.as_string(),
f"{text}\nBody",
)
+ self.assertEqual(
+ message.as_bytes(),
+ f"{text}\nBody".encode(),
+ )
# XXX: Need subclassing tests.
# For adding subclassed objects, make sure the usual rules apply (subclass
diff --git a/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst b/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
new file mode 100644
index 00000000000000..e6333e724972c5
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
@@ -0,0 +1,4 @@
+:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) headers
+that are unsafely folded or delimited; see
+:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas
+Bloemsaat and Petr Viktorin in :gh:`121650`).

View File

@ -13,11 +13,11 @@ URL: https://www.python.org/
# WARNING When rebasing to a new Python version, # WARNING When rebasing to a new Python version,
# remember to update the python3-docs package as well # remember to update the python3-docs package as well
%global general_version %{pybasever}.12 %global general_version %{pybasever}.13
#global prerel ... #global prerel ...
%global upstream_version %{general_version}%{?prerel} %global upstream_version %{general_version}%{?prerel}
Version: %{general_version}%{?prerel:~%{prerel}} Version: %{general_version}%{?prerel:~%{prerel}}
Release: 6%{?dist} Release: 1%{?dist}
License: Python-2.0.1 License: Python-2.0.1
@ -434,36 +434,6 @@ Patch462: 00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch
# will not show the Python functions, irrespective of this patch. # will not show the Python functions, irrespective of this patch.
Patch464: 00464-enable-pac-and-bti-protections-for-aarch64.patch Patch464: 00464-enable-pac-and-bti-protections-for-aarch64.patch
# 00471 # 37c05f26d11e8e24f2a760167015a267996b1d69
# CVE-2025-12084
#
# * gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146)
# * gh-142754: Ensure that Element & Attr instances have the ownerDocument attribute (GH-142794)
Patch471: 00471-cve-2025-12084.patch
# 00472 # 2ba215eaba508b2cdd7c3acfdf3b9a6e32872274
# CVE-2025-13836
#
# [3.12] gh-119451: Fix a potential denial of service in http.client (GH-119454) (#142140)
#
# gh-119451: Fix a potential denial of service in http.client (GH-119454)
#
# Reading the whole body of the HTTP response could cause OOM if
# the Content-Length value is too large even if the server does not send
# a large amount of data. Now the HTTP client reads large data by chunks,
# therefore the amount of consumed memory is proportional to the amount
# of sent data.
Patch472: 00472-cve-2025-13836.patch
# 00473 # dd705786aa0c1ccfde913858598e34e1f196be2e
# CVE-2026-0865
#
# 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
Patch473: 00473-cve-2026-0865.patch
# 00474 # 837ddca0372fa87ff9cee47142200caa21e77def # 00474 # 837ddca0372fa87ff9cee47142200caa21e77def
# CVE-2025-15366 # CVE-2025-15366
# #
@ -480,12 +450,6 @@ Patch474: 00474-cve-2025-15366.patch
# (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) # (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7)
Patch475: 00475-cve-2025-15367.patch Patch475: 00475-cve-2025-15367.patch
# 00476
# CVE-2026-1299
#
# gh-144125: email: verify headers are sound in BytesGenerator
Patch476: 00476-cve-2026-1299.patch
# 00478 # eb93352dc8e31f4d52546b84daad875e6ff7f29e # 00478 # eb93352dc8e31f4d52546b84daad875e6ff7f29e
# CVE-2026-4519 # CVE-2026-4519
# #
@ -1857,6 +1821,11 @@ CheckPython optimized
# ====================================================== # ======================================================
%changelog %changelog
* Thu Apr 16 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.12.13-1
- Update to 3.12.13
- Security fixes for CVE-2025-6075, CVE-2025-13837, CVE-2025-15282, CVE-2025-59375, CVE-2026-0672
Related: RHEL-167886, RHEL-168120
* Fri Mar 27 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.12.12-6 * Fri Mar 27 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.12.12-6
- Security fix for CVE-2026-4519 - Security fix for CVE-2026-4519
Resolves: RHEL-158079 Resolves: RHEL-158079

View File

@ -1,2 +1,2 @@
SHA512 (Python-3.12.12.tar.xz) = 4b99d240dd96a6e154909dcffe87f8bb38193d634cd80a1c3d9e819b7a63af2afa46d5e6423e81f00dd388840dc29a4a71580f6aa1ce9a12e559c1d63f65a205 SHA512 (Python-3.12.13.tar.xz) = e1eb66f0b34581f0155e3ce25ba72cf0b4b1107672ed0ad3e86bcfe616945c9204c41ffc492f32b1066b9154913ff88343038967ad8711dd05e6f2332fdb735b
SHA512 (Python-3.12.12.tar.xz.asc) = 32c10fd427c6f9f11595493d1b4d4c3cade85bffd439fe11e8b0b2c619e06734097b6aaedfdb4fe035b7fdd7196714dba77cdc806923e4454d5bcf60056991a0 SHA512 (Python-3.12.13.tar.xz.asc) = 903fd3baa7e29891bb00fb159ec9c43804a71002c4cd38902d25bf4e5167f856b37d211a5b1098ee60e1ea41f8a10a1596dd2382edc6d7367d55dd4154807fc7