Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions SPECS/python3/CVE-2026-1299.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
From 423815ef64b3cdeb99f0800446c1e2c7c7f58a88 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <seth@python.org>
Date: Fri, 23 Jan 2026 08:59:35 -0600
Subject: [PATCH] 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>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/python/cpython/pull/144188.patch
---
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 47b9df8..8cbc43e 100644
--- a/Lib/email/generator.py
+++ b/Lib/email/generator.py
@@ -22,6 +22,7 @@ NL = '\n' # XXX: no longer used by the code below.
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 @@ class BytesGenerator(Generator):
# 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 c75a842..3ca79ed 100644
--- a/Lib/test/test_email/test_generator.py
+++ b/Lib/test/test_email/test_generator.py
@@ -313,7 +313,7 @@ class TestGenerator(TestGeneratorBase, TestEmailBase):
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 @@ class TestGenerator(TestGeneratorBase, TestEmailBase):

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 baa35fd..71ec0fe 100644
--- a/Lib/test/test_email/test_policy.py
+++ b/Lib/test/test_email/test_policy.py
@@ -296,7 +296,7 @@ class PolicyAPITests(unittest.TestCase):
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 @@ class PolicyAPITests(unittest.TestCase):
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 0000000..e6333e7
--- /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`).
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/python3/python3.spec
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Summary: A high-level scripting language
Name: python3
Version: 3.12.9
Release: 8%{?dist}
Release: 9%{?dist}
License: PSF
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -29,6 +29,7 @@ Patch9: CVE-2025-13837.patch
Patch10: CVE-2025-11468.patch
Patch11: CVE-2026-0672.patch
Patch12: CVE-2026-0865.patch
Patch13: CVE-2026-1299.patch

BuildRequires: bzip2-devel
BuildRequires: expat-devel >= 2.1.0
Expand Down Expand Up @@ -251,6 +252,9 @@ rm -rf %{buildroot}%{_bindir}/__pycache__
%{_libdir}/python%{majmin}/test/*

%changelog
* Mon Feb 16 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.12.9-9
- Patch for CVE-2026-1299

* Wed Jan 28 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 3.12.9-8
- Patch for CVE-2026-0865, CVE-2025-11468, CVE-2026-0672

Expand Down
6 changes: 3 additions & 3 deletions toolkit/resources/manifests/package/pkggen_core_aarch64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,9 @@ ca-certificates-base-3.0.0-14.azl3.noarch.rpm
ca-certificates-3.0.0-14.azl3.noarch.rpm
dwz-0.14-2.azl3.aarch64.rpm
unzip-6.0-22.azl3.aarch64.rpm
python3-3.12.9-8.azl3.aarch64.rpm
python3-devel-3.12.9-8.azl3.aarch64.rpm
python3-libs-3.12.9-8.azl3.aarch64.rpm
python3-3.12.9-9.azl3.aarch64.rpm
python3-devel-3.12.9-9.azl3.aarch64.rpm
python3-libs-3.12.9-9.azl3.aarch64.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
which-2.21-8.azl3.aarch64.rpm
Expand Down
6 changes: 3 additions & 3 deletions toolkit/resources/manifests/package/pkggen_core_x86_64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,9 @@ ca-certificates-base-3.0.0-14.azl3.noarch.rpm
ca-certificates-3.0.0-14.azl3.noarch.rpm
dwz-0.14-2.azl3.x86_64.rpm
unzip-6.0-22.azl3.x86_64.rpm
python3-3.12.9-8.azl3.x86_64.rpm
python3-devel-3.12.9-8.azl3.x86_64.rpm
python3-libs-3.12.9-8.azl3.x86_64.rpm
python3-3.12.9-9.azl3.x86_64.rpm
python3-devel-3.12.9-9.azl3.x86_64.rpm
python3-libs-3.12.9-9.azl3.x86_64.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-pygments-2.7.4-2.azl3.noarch.rpm
which-2.21-8.azl3.x86_64.rpm
Expand Down
14 changes: 7 additions & 7 deletions toolkit/resources/manifests/package/toolchain_aarch64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -531,19 +531,19 @@ pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm
pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm
python-markupsafe-debuginfo-2.1.3-1.azl3.aarch64.rpm
python-wheel-wheel-0.43.0-1.azl3.noarch.rpm
python3-3.12.9-8.azl3.aarch64.rpm
python3-3.12.9-9.azl3.aarch64.rpm
python3-audit-3.1.2-1.azl3.aarch64.rpm
python3-cracklib-2.9.11-1.azl3.aarch64.rpm
python3-curses-3.12.9-8.azl3.aarch64.rpm
python3-curses-3.12.9-9.azl3.aarch64.rpm
python3-Cython-3.0.5-2.azl3.aarch64.rpm
python3-debuginfo-3.12.9-8.azl3.aarch64.rpm
python3-devel-3.12.9-8.azl3.aarch64.rpm
python3-debuginfo-3.12.9-9.azl3.aarch64.rpm
python3-devel-3.12.9-9.azl3.aarch64.rpm
python3-flit-core-3.9.0-1.azl3.noarch.rpm
python3-gpg-1.23.2-2.azl3.aarch64.rpm
python3-jinja2-3.1.2-3.azl3.noarch.rpm
python3-libcap-ng-0.8.4-1.azl3.aarch64.rpm
python3-libmount-2.40.2-3.azl3.aarch64.rpm
python3-libs-3.12.9-8.azl3.aarch64.rpm
python3-libs-3.12.9-9.azl3.aarch64.rpm
python3-libxml2-2.11.5-8.azl3.aarch64.rpm
python3-lxml-4.9.3-1.azl3.aarch64.rpm
python3-magic-5.45-1.azl3.noarch.rpm
Expand All @@ -555,8 +555,8 @@ python3-pygments-2.7.4-2.azl3.noarch.rpm
python3-rpm-4.18.2-1.azl3.aarch64.rpm
python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-test-3.12.9-8.azl3.aarch64.rpm
python3-tools-3.12.9-8.azl3.aarch64.rpm
python3-test-3.12.9-9.azl3.aarch64.rpm
python3-tools-3.12.9-9.azl3.aarch64.rpm
python3-wheel-0.43.0-1.azl3.noarch.rpm
readline-8.2-2.azl3.aarch64.rpm
readline-debuginfo-8.2-2.azl3.aarch64.rpm
Expand Down
14 changes: 7 additions & 7 deletions toolkit/resources/manifests/package/toolchain_x86_64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -539,19 +539,19 @@ pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm
pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm
python-markupsafe-debuginfo-2.1.3-1.azl3.x86_64.rpm
python-wheel-wheel-0.43.0-1.azl3.noarch.rpm
python3-3.12.9-8.azl3.x86_64.rpm
python3-3.12.9-9.azl3.x86_64.rpm
python3-audit-3.1.2-1.azl3.x86_64.rpm
python3-cracklib-2.9.11-1.azl3.x86_64.rpm
python3-curses-3.12.9-8.azl3.x86_64.rpm
python3-curses-3.12.9-9.azl3.x86_64.rpm
python3-Cython-3.0.5-2.azl3.x86_64.rpm
python3-debuginfo-3.12.9-8.azl3.x86_64.rpm
python3-devel-3.12.9-8.azl3.x86_64.rpm
python3-debuginfo-3.12.9-9.azl3.x86_64.rpm
python3-devel-3.12.9-9.azl3.x86_64.rpm
python3-flit-core-3.9.0-1.azl3.noarch.rpm
python3-gpg-1.23.2-2.azl3.x86_64.rpm
python3-jinja2-3.1.2-3.azl3.noarch.rpm
python3-libcap-ng-0.8.4-1.azl3.x86_64.rpm
python3-libmount-2.40.2-3.azl3.x86_64.rpm
python3-libs-3.12.9-8.azl3.x86_64.rpm
python3-libs-3.12.9-9.azl3.x86_64.rpm
python3-libxml2-2.11.5-8.azl3.x86_64.rpm
python3-lxml-4.9.3-1.azl3.x86_64.rpm
python3-magic-5.45-1.azl3.noarch.rpm
Expand All @@ -563,8 +563,8 @@ python3-pygments-2.7.4-2.azl3.noarch.rpm
python3-rpm-4.18.2-1.azl3.x86_64.rpm
python3-rpm-generators-14-11.azl3.noarch.rpm
python3-setuptools-69.0.3-5.azl3.noarch.rpm
python3-test-3.12.9-8.azl3.x86_64.rpm
python3-tools-3.12.9-8.azl3.x86_64.rpm
python3-test-3.12.9-9.azl3.x86_64.rpm
python3-tools-3.12.9-9.azl3.x86_64.rpm
python3-wheel-0.43.0-1.azl3.noarch.rpm
readline-8.2-2.azl3.x86_64.rpm
readline-debuginfo-8.2-2.azl3.x86_64.rpm
Expand Down
Loading