Skip to content

Commit a185a42

Browse files
azurelinux-securityKanishk-BansalBinduSri-6522866
authored
[AutoPR- Security] Patch python3 for CVE-2026-0865, CVE-2025-12084 [MEDIUM] (#15641)
Co-authored-by: Kanishk Bansal <103916909+Kanishk-Bansal@users.noreply.github.com> Co-authored-by: BinduSri-6522866 <v-badabala@microsoft.com>
1 parent b2a3370 commit a185a42

7 files changed

Lines changed: 280 additions & 27 deletions

File tree

SPECS/python3/CVE-2025-12084.patch

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
From f4eb9ab014545b521fb261b80adfa6d138e7e092 Mon Sep 17 00:00:00 2001
2+
From: Seth Michael Larson <seth@python.org>
3+
Date: Wed, 3 Dec 2025 01:16:37 -0600
4+
Subject: [PATCH 1/4] gh-142145: Remove quadratic behavior in node ID cache
5+
clearing (GH-142146)
6+
7+
* Remove quadratic behavior in node ID cache clearing
8+
9+
Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com>
10+
11+
* Add news fragment
12+
13+
---------
14+
(cherry picked from commit 08d8e18ad81cd45bc4a27d6da478b51ea49486e4)
15+
16+
Co-authored-by: Seth Michael Larson <seth@python.org>
17+
Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com>
18+
19+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
20+
Upstream-reference: https://github.com/python/cpython/pull/142213.patch
21+
---
22+
Lib/test/test_minidom.py | 33 ++++++++++++++++++-
23+
Lib/xml/dom/minidom.py | 11 ++-----
24+
...-12-01-09-36-45.gh-issue-142145.tcAUhg.rst | 6 ++++
25+
3 files changed, 41 insertions(+), 9 deletions(-)
26+
create mode 100644 Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst
27+
28+
diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py
29+
index 9762025..9f7f5b2 100644
30+
--- a/Lib/test/test_minidom.py
31+
+++ b/Lib/test/test_minidom.py
32+
@@ -2,6 +2,7 @@
33+
34+
import copy
35+
import pickle
36+
+import time
37+
import io
38+
from test import support
39+
import unittest
40+
@@ -9,7 +10,7 @@ import unittest
41+
import pyexpat
42+
import xml.dom.minidom
43+
44+
-from xml.dom.minidom import parse, Node, Document, parseString
45+
+from xml.dom.minidom import parse, Attr, Node, Document, Element, parseString
46+
from xml.dom.minidom import getDOMImplementation
47+
from xml.parsers.expat import ExpatError
48+
49+
@@ -163,6 +164,36 @@ class MinidomTest(unittest.TestCase):
50+
self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
51+
dom.unlink()
52+
53+
+ @support.requires_resource('cpu')
54+
+ def testAppendChildNoQuadraticComplexity(self):
55+
+ impl = getDOMImplementation()
56+
+
57+
+ newdoc = impl.createDocument(None, "some_tag", None)
58+
+ top_element = newdoc.documentElement
59+
+ children = [newdoc.createElement(f"child-{i}") for i in range(1, 2 ** 15 + 1)]
60+
+ element = top_element
61+
+
62+
+ start = time.monotonic()
63+
+ for child in children:
64+
+ element.appendChild(child)
65+
+ element = child
66+
+ end = time.monotonic()
67+
+
68+
+ # This example used to take at least 30 seconds.
69+
+ # Conservative assertion due to the wide variety of systems and
70+
+ # build configs timing based tests wind up run under.
71+
+ # A --with-address-sanitizer --with-pydebug build on a rpi5 still
72+
+ # completes this loop in <0.5 seconds.
73+
+ self.assertLess(end - start, 4)
74+
+
75+
+ def testSetAttributeNodeWithoutOwnerDocument(self):
76+
+ # regression test for gh-142754
77+
+ elem = Element("test")
78+
+ attr = Attr("id")
79+
+ attr.value = "test-id"
80+
+ elem.setAttributeNode(attr)
81+
+ self.assertEqual(elem.getAttribute("id"), "test-id")
82+
+
83+
def testAppendChildFragment(self):
84+
dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
85+
dom.documentElement.appendChild(frag)
86+
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
87+
index d09ef5e..e4e8b42 100644
88+
--- a/Lib/xml/dom/minidom.py
89+
+++ b/Lib/xml/dom/minidom.py
90+
@@ -292,13 +292,6 @@ def _append_child(self, node):
91+
childNodes.append(node)
92+
node.parentNode = self
93+
94+
-def _in_document(node):
95+
- # return True iff node is part of a document tree
96+
- while node is not None:
97+
- if node.nodeType == Node.DOCUMENT_NODE:
98+
- return True
99+
- node = node.parentNode
100+
- return False
101+
102+
def _write_data(writer, data):
103+
"Writes datachars to writer."
104+
@@ -355,6 +348,7 @@ class Attr(Node):
105+
def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None,
106+
prefix=None):
107+
self.ownerElement = None
108+
+ self.ownerDocument = None
109+
self._name = qName
110+
self.namespaceURI = namespaceURI
111+
self._prefix = prefix
112+
@@ -678,6 +672,7 @@ class Element(Node):
113+
114+
def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None,
115+
localName=None):
116+
+ self.ownerDocument = None
117+
self.parentNode = None
118+
self.tagName = self.nodeName = tagName
119+
self.prefix = prefix
120+
@@ -1537,7 +1532,7 @@ def _clear_id_cache(node):
121+
if node.nodeType == Node.DOCUMENT_NODE:
122+
node._id_cache.clear()
123+
node._id_search_stack = None
124+
- elif _in_document(node):
125+
+ elif node.ownerDocument:
126+
node.ownerDocument._id_cache.clear()
127+
node.ownerDocument._id_search_stack= None
128+
129+
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
130+
new file mode 100644
131+
index 0000000..05c7df3
132+
--- /dev/null
133+
+++ b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst
134+
@@ -0,0 +1,6 @@
135+
+Remove quadratic behavior in ``xml.minidom`` node ID cache clearing. In order
136+
+to do this without breaking existing users, we also add the *ownerDocument*
137+
+attribute to :mod:`xml.dom.minidom` elements and attributes created by directly
138+
+instantiating the ``Element`` or ``Attr`` class. Note that this way of creating
139+
+nodes is not supported; creator functions like
140+
+:py:meth:`xml.dom.Document.documentElement` should be used instead.
141+
--
142+
2.45.4
143+

SPECS/python3/CVE-2026-0865.patch

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
From 123bfbbe9074ef7fa28e1e7b25575665296560fa Mon Sep 17 00:00:00 2001
2+
From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com>
3+
Date: Sat, 17 Jan 2026 10:23:57 -0800
4+
Subject: [PATCH] [3.10] gh-143916: Reject control characters in
5+
wsgiref.headers.Headers (GH-143917) (GH-143973)
6+
7+
gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917)
8+
9+
* Add 'test.support' fixture for C0 control characters
10+
* gh-143916: Reject control characters in wsgiref.headers.Headers
11+
12+
(cherry picked from commit f7fceed79ca1bceae8dbe5ba5bc8928564da7211)
13+
(cherry picked from commit 22e4d55285cee52bc4dbe061324e5f30bd4dee58)
14+
15+
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
16+
Co-authored-by: Seth Michael Larson <seth@python.org>
17+
18+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
19+
Upstream-reference: https://github.com/python/cpython/pull/143976.patch
20+
---
21+
Lib/test/support/__init__.py | 7 +++++++
22+
Lib/test/test_wsgiref.py | 12 +++++++++++-
23+
Lib/wsgiref/headers.py | 3 +++
24+
.../2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst | 2 ++
25+
4 files changed, 23 insertions(+), 1 deletion(-)
26+
create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
27+
28+
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
29+
index 6dc0813..ea9a88d 100644
30+
--- a/Lib/test/support/__init__.py
31+
+++ b/Lib/test/support/__init__.py
32+
@@ -3305,3 +3305,10 @@ def adjust_int_max_str_digits(max_digits):
33+
yield
34+
finally:
35+
sys.set_int_max_str_digits(current)
36+
+
37+
+
38+
+def control_characters_c0() -> list[str]:
39+
+ """Returns a list of C0 control characters as strings.
40+
+ C0 control characters defined as the byte range 0x00-0x1F, and 0x7F.
41+
+ """
42+
+ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"]
43+
diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py
44+
index 3e76e01..d5d3f65 100644
45+
--- a/Lib/test/test_wsgiref.py
46+
+++ b/Lib/test/test_wsgiref.py
47+
@@ -1,6 +1,6 @@
48+
from unittest import mock
49+
from test import support
50+
-from test.support import socket_helper
51+
+from test.support import socket_helper, control_characters_c0
52+
from test.test_httpservers import NoLogRequestHandler
53+
from unittest import TestCase
54+
from wsgiref.util import setup_testing_defaults
55+
@@ -526,6 +526,16 @@ class HeaderTests(TestCase):
56+
'\r\n'
57+
)
58+
59+
+ def testRaisesControlCharacters(self):
60+
+ headers = Headers()
61+
+ for c0 in control_characters_c0():
62+
+ self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val")
63+
+ self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}")
64+
+ self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param")
65+
+ self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param")
66+
+ self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}")
67+
+
68+
+
69+
class ErrorHandler(BaseCGIHandler):
70+
"""Simple handler subclass for testing BaseHandler"""
71+
72+
diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py
73+
index fab851c..fd98e85 100644
74+
--- a/Lib/wsgiref/headers.py
75+
+++ b/Lib/wsgiref/headers.py
76+
@@ -9,6 +9,7 @@ written by Barry Warsaw.
77+
# existence of which force quoting of the parameter value.
78+
import re
79+
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
80+
+_control_chars_re = re.compile(r'[\x00-\x1F\x7F]')
81+
82+
def _formatparam(param, value=None, quote=1):
83+
"""Convenience function to format and return a key=value pair.
84+
@@ -41,6 +42,8 @@ class Headers:
85+
def _convert_string_type(self, value):
86+
"""Convert/check value type."""
87+
if type(value) is str:
88+
+ if _control_chars_re.search(value):
89+
+ raise ValueError("Control characters not allowed in headers")
90+
return value
91+
raise AssertionError("Header names/values must be"
92+
" of type str (got {0})".format(repr(value)))
93+
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
94+
new file mode 100644
95+
index 0000000..44bd0b2
96+
--- /dev/null
97+
+++ b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst
98+
@@ -0,0 +1,2 @@
99+
+Reject C0 control characters within wsgiref.headers.Headers fields, values,
100+
+and parameters.
101+
--
102+
2.45.4
103+

SPECS/python3/python3.spec

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
Summary: A high-level scripting language
1313
Name: python3
1414
Version: 3.9.19
15-
Release: 18%{?dist}
15+
Release: 19%{?dist}
1616
License: PSF
1717
Vendor: Microsoft Corporation
1818
Distribution: Mariner
@@ -41,6 +41,8 @@ Patch17: CVE-2025-8291.patch
4141
Patch18: CVE-2025-6075.patch
4242
Patch19: CVE-2026-0672.patch
4343
Patch20: CVE-2026-1299.patch
44+
Patch21: CVE-2025-12084.patch
45+
Patch22: CVE-2026-0865.patch
4446

4547
# Patch for setuptools, resolved in 65.5.1
4648
Patch1000: CVE-2022-40897.patch
@@ -208,6 +210,8 @@ The test package contains all regression tests for Python as well as the modules
208210
%patch18 -p1
209211
%patch19 -p1
210212
%patch20 -p1
213+
%patch21 -p1
214+
%patch22 -p1
211215

212216
%build
213217
# Remove GCC specs and build environment linker scripts
@@ -383,6 +387,9 @@ make test TESTOPTS="-x test_multiprocessing_spawn -x test_socket -x test_email"
383387
%{_libdir}/python%{majmin}/test/*
384388

385389
%changelog
390+
* Fri Jan 30 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.9.19-19
391+
- Patch for CVE-2026-0865, CVE-2025-12084
392+
386393
* Wed Jan 28 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.9.19-18
387394
- Patch for CVE-2026-1299, CVE-2026-0672
388395

toolkit/resources/manifests/package/pkggen_core_aarch64.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,10 @@ ca-certificates-base-2.0.0-25.cm2.noarch.rpm
237237
ca-certificates-2.0.0-25.cm2.noarch.rpm
238238
dwz-0.14-2.cm2.aarch64.rpm
239239
unzip-6.0-22.cm2.aarch64.rpm
240-
python3-3.9.19-18.cm2.aarch64.rpm
241-
python3-devel-3.9.19-18.cm2.aarch64.rpm
242-
python3-libs-3.9.19-18.cm2.aarch64.rpm
243-
python3-setuptools-3.9.19-18.cm2.noarch.rpm
240+
python3-3.9.19-19.cm2.aarch64.rpm
241+
python3-devel-3.9.19-19.cm2.aarch64.rpm
242+
python3-libs-3.9.19-19.cm2.aarch64.rpm
243+
python3-setuptools-3.9.19-19.cm2.noarch.rpm
244244
python3-pygments-2.4.2-7.cm2.noarch.rpm
245245
which-2.21-8.cm2.aarch64.rpm
246246
libselinux-3.2-1.cm2.aarch64.rpm

toolkit/resources/manifests/package/pkggen_core_x86_64.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,10 @@ ca-certificates-base-2.0.0-25.cm2.noarch.rpm
237237
ca-certificates-2.0.0-25.cm2.noarch.rpm
238238
dwz-0.14-2.cm2.x86_64.rpm
239239
unzip-6.0-22.cm2.x86_64.rpm
240-
python3-3.9.19-18.cm2.x86_64.rpm
241-
python3-devel-3.9.19-18.cm2.x86_64.rpm
242-
python3-libs-3.9.19-18.cm2.x86_64.rpm
243-
python3-setuptools-3.9.19-18.cm2.noarch.rpm
240+
python3-3.9.19-19.cm2.x86_64.rpm
241+
python3-devel-3.9.19-19.cm2.x86_64.rpm
242+
python3-libs-3.9.19-19.cm2.x86_64.rpm
243+
python3-setuptools-3.9.19-19.cm2.noarch.rpm
244244
python3-pygments-2.4.2-7.cm2.noarch.rpm
245245
which-2.21-8.cm2.x86_64.rpm
246246
libselinux-3.2-1.cm2.x86_64.rpm

toolkit/resources/manifests/package/toolchain_aarch64.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -510,28 +510,28 @@ procps-ng-devel-3.3.17-2.cm2.aarch64.rpm
510510
procps-ng-lang-3.3.17-2.cm2.aarch64.rpm
511511
pyproject-rpm-macros-1.0.0~rc1-4.cm2.noarch.rpm
512512
python-markupsafe-debuginfo-2.1.0-1.cm2.aarch64.rpm
513-
python3-3.9.19-18.cm2.aarch64.rpm
513+
python3-3.9.19-19.cm2.aarch64.rpm
514514
python3-audit-3.0.6-8.cm2.aarch64.rpm
515515
python3-cracklib-2.9.7-5.cm2.aarch64.rpm
516-
python3-curses-3.9.19-18.cm2.aarch64.rpm
516+
python3-curses-3.9.19-19.cm2.aarch64.rpm
517517
python3-Cython-0.29.33-2.cm2.aarch64.rpm
518-
python3-debuginfo-3.9.19-18.cm2.aarch64.rpm
519-
python3-devel-3.9.19-18.cm2.aarch64.rpm
518+
python3-debuginfo-3.9.19-19.cm2.aarch64.rpm
519+
python3-devel-3.9.19-19.cm2.aarch64.rpm
520520
python3-gpg-1.16.0-2.cm2.aarch64.rpm
521521
python3-jinja2-3.0.3-7.cm2.noarch.rpm
522522
python3-libcap-ng-0.8.2-2.cm2.aarch64.rpm
523-
python3-libs-3.9.19-18.cm2.aarch64.rpm
523+
python3-libs-3.9.19-19.cm2.aarch64.rpm
524524
python3-libxml2-2.10.4-10.cm2.aarch64.rpm
525525
python3-lxml-4.9.1-1.cm2.aarch64.rpm
526526
python3-magic-5.40-3.cm2.noarch.rpm
527527
python3-markupsafe-2.1.0-1.cm2.aarch64.rpm
528528
python3-newt-0.52.21-5.cm2.aarch64.rpm
529-
python3-pip-3.9.19-18.cm2.noarch.rpm
529+
python3-pip-3.9.19-19.cm2.noarch.rpm
530530
python3-pygments-2.4.2-7.cm2.noarch.rpm
531531
python3-rpm-4.18.0-4.cm2.aarch64.rpm
532-
python3-setuptools-3.9.19-18.cm2.noarch.rpm
533-
python3-test-3.9.19-18.cm2.aarch64.rpm
534-
python3-tools-3.9.19-18.cm2.aarch64.rpm
532+
python3-setuptools-3.9.19-19.cm2.noarch.rpm
533+
python3-test-3.9.19-19.cm2.aarch64.rpm
534+
python3-tools-3.9.19-19.cm2.aarch64.rpm
535535
readline-8.1-1.cm2.aarch64.rpm
536536
readline-debuginfo-8.1-1.cm2.aarch64.rpm
537537
readline-devel-8.1-1.cm2.aarch64.rpm

toolkit/resources/manifests/package/toolchain_x86_64.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -516,28 +516,28 @@ procps-ng-devel-3.3.17-2.cm2.x86_64.rpm
516516
procps-ng-lang-3.3.17-2.cm2.x86_64.rpm
517517
pyproject-rpm-macros-1.0.0~rc1-4.cm2.noarch.rpm
518518
python-markupsafe-debuginfo-2.1.0-1.cm2.x86_64.rpm
519-
python3-3.9.19-18.cm2.x86_64.rpm
519+
python3-3.9.19-19.cm2.x86_64.rpm
520520
python3-audit-3.0.6-8.cm2.x86_64.rpm
521521
python3-cracklib-2.9.7-5.cm2.x86_64.rpm
522-
python3-curses-3.9.19-18.cm2.x86_64.rpm
522+
python3-curses-3.9.19-19.cm2.x86_64.rpm
523523
python3-Cython-0.29.33-2.cm2.x86_64.rpm
524-
python3-debuginfo-3.9.19-18.cm2.x86_64.rpm
525-
python3-devel-3.9.19-18.cm2.x86_64.rpm
524+
python3-debuginfo-3.9.19-19.cm2.x86_64.rpm
525+
python3-devel-3.9.19-19.cm2.x86_64.rpm
526526
python3-gpg-1.16.0-2.cm2.x86_64.rpm
527527
python3-jinja2-3.0.3-7.cm2.noarch.rpm
528528
python3-libcap-ng-0.8.2-2.cm2.x86_64.rpm
529-
python3-libs-3.9.19-18.cm2.x86_64.rpm
529+
python3-libs-3.9.19-19.cm2.x86_64.rpm
530530
python3-libxml2-2.10.4-10.cm2.x86_64.rpm
531531
python3-lxml-4.9.1-1.cm2.x86_64.rpm
532532
python3-magic-5.40-3.cm2.noarch.rpm
533533
python3-markupsafe-2.1.0-1.cm2.x86_64.rpm
534534
python3-newt-0.52.21-5.cm2.x86_64.rpm
535-
python3-pip-3.9.19-18.cm2.noarch.rpm
535+
python3-pip-3.9.19-19.cm2.noarch.rpm
536536
python3-pygments-2.4.2-7.cm2.noarch.rpm
537537
python3-rpm-4.18.0-4.cm2.x86_64.rpm
538-
python3-setuptools-3.9.19-18.cm2.noarch.rpm
539-
python3-test-3.9.19-18.cm2.x86_64.rpm
540-
python3-tools-3.9.19-18.cm2.x86_64.rpm
538+
python3-setuptools-3.9.19-19.cm2.noarch.rpm
539+
python3-test-3.9.19-19.cm2.x86_64.rpm
540+
python3-tools-3.9.19-19.cm2.x86_64.rpm
541541
readline-8.1-1.cm2.x86_64.rpm
542542
readline-debuginfo-8.1-1.cm2.x86_64.rpm
543543
readline-devel-8.1-1.cm2.x86_64.rpm

0 commit comments

Comments
 (0)