Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
cb85e6e
[3.10] gh-143916: Reject control characters in wsgiref.headers.Headers
gpshead Jan 20, 2026
39aa82a
[3.10] gh-143925: Reject control characters in data: URL mediatypes (…
sethmlarson Jan 25, 2026
ab10995
[3.10] gh-143919: Reject control characters in http cookies (#144094)
sethmlarson Jan 25, 2026
b052613
[3.10] gh-144125: email: verify headers are sound in BytesGenerator (…
miss-islington Jan 25, 2026
16d68aa
[3.10] gh-119452: Fix a potential virtual memory allocation denial of…
miss-islington Jan 25, 2026
4af6ac6
[3.10] gh-142145: Remove quadratic behavior in node ID cache clearing…
miss-islington Jan 25, 2026
d0bd801
[3.10] gh-119451: Fix a potential denial of service in http.client (G…
miss-islington Jan 25, 2026
085d85f
[3.10] gh-74453: Add stronger security warning to os.path.commonprefix
miss-islington Feb 3, 2026
1229f55
[3.10] gh-144484: Warn users not to use wsgiref in production
miss-islington Feb 5, 2026
9b8fefb
[3.10] gh-119342: Fix a potential denial of service in plistlib (GH-1…
serhiy-storchaka Mar 2, 2026
72b2646
[3.10] gh-144833: Fix use-after-free in SSL module when SSL_new() fai…
miss-islington Mar 2, 2026
530073a
[3.10] gh-143916: Allow HTAB in wsgiref header values (#145140)
miss-islington Mar 2, 2026
bbeffdf
[3.10] gh-144363: Update bundled libexpat to 2.7.4 (GH-144365) (#144515)
StanFromIreland Mar 2, 2026
1aa4421
[3.10] gh-143935: Email preserve parens when folding comments (GH-143…
edgarrmondragon Mar 2, 2026
1b02d47
[3.10] gh-143930: Reject leading dashes in webbrowser URLs (GH-143931…
tomcruiseqi Mar 24, 2026
0ce8343
[3.10] gh-143930: Tweak the exception message and increase test cover…
miss-islington Apr 3, 2026
b4dfdd8
[3.10] gh-137586: Open external osascript program with absolute path …
miss-islington Apr 7, 2026
266640f
[3.10] gh-146083: Upgrade bundled Expat to 2.7.5 (GH-146085) (#146608)
StanFromIreland Apr 8, 2026
af2c6c5
[3.10] gh-145986: Avoid unbound C recursion in `conv_content_model` i…
StanFromIreland Apr 8, 2026
a8ff95c
[3.10] gh-148169: Fix webbrowser `%action` substitution bypass of das…
StanFromIreland Apr 13, 2026
c8d2f0f
[3.10] gh-148395: Fix a possible UAF in `{LZMA,BZ2}Decompressor` (GH-…
StanFromIreland Apr 13, 2026
2e2b37c
[3.10] gh-145506: Fixes CVE-2026-2297 by ensuring SourcelessFileLoade…
miss-islington Apr 30, 2026
207f2a4
[3.10] gh-141707: Skip TarInfo DIRTYPE normalization during GNU long …
miss-islington Apr 30, 2026
797bc58
[3.10] gh-144370: Disallow usage of control characters in status in w…
vstinner May 17, 2026
016157f
[3.10] gh-151981: Make tarfile._Stream.seek break at EOF (GH-151982) …
miss-islington Jun 27, 2026
04e5bc8
[3.10] gh-87451: Apply CVE-2021-4189 PASV fix to ftplib.ftpcp() (GH-1…
miss-islington Jun 27, 2026
18fd839
[3.10] gh-146211: Reject CR/LF in HTTP tunnel request headers (GH-146…
sethmlarson Jun 27, 2026
393784b
[3.10] gh-145599, CVE 2026-3644: Reject control characters in `http.c…
vstinner Jun 27, 2026
4efce7e
[3.10] gh-150743: Limit trailer lines and interim responses read by h…
miss-islington Jun 28, 2026
424c1e3
[3.10] gh-150599: Prevent bz2 decompressor reuse after errors (#15060…
StanFromIreland Jul 4, 2026
fa57774
[3.10] gh-149486: tarfile.data_filter: validate written link target (…
StanFromIreland Jul 6, 2026
7324f7b
[3.10] gh-151987: Pass filter_function to TarFile._extract_one() duri…
miss-islington Jul 11, 2026
140af36
[3.10] gh-153438: Update NuGet download URL (GH-153482) (GH-153515) (…
miss-islington Aug 10, 2026
5c5fac3
[3.10] gh-146581: Fix vulnerability in shutil.unpack_archive() for ZI…
miss-islington Aug 10, 2026
d76d4f3
[3.10] gh-100372: Use BIO_eof to detect EOF for SSL_FILETYPE_ASN1 (GH…
miss-islington Aug 10, 2026
9a0f5a6
[3.10] gh-149017: Upgrade bundled Expat to 2.8.0 (#149020) (#149075)
StanFromIreland Aug 10, 2026
f43369a
[3.10] gh-149776: Skip UDP Lite tests if it's not supported (#149777)…
vstinner Aug 10, 2026
81a27a9
[3.10] gh-149079: Fix O(n^2) canonical ordering in unicodedata.normal…
miss-islington Aug 10, 2026
11c739e
[3.10] gh-109638: Fix exponential time in csv.Sniffer for doubled quo…
miss-islington Aug 10, 2026
31c0075
[3.10] gh-152674: Avoid quadratic behavior in xml.etree.ElementPath i…
miss-islington Aug 10, 2026
59ac1ca
[3.10] gh-153030: Fix quadratic complexity in incremental parsing in …
serhiy-storchaka Aug 10, 2026
afabbd2
[3.10] gh-151558: Fix symlink escape via `tarfile` hardlink-extractio…
StanFromIreland Aug 10, 2026
1a6c57f
[3.10] gh-146333: Fix quadratic regex backtracking in configparser op…
encukou Aug 10, 2026
4202bdf
[3.10] gh-143927: Normalize all line endings (CR, CRLF, and LF) in co…
miss-islington Aug 10, 2026
dd92d43
[3.10] gh-98820: Fix quadratic time in csv.Sniffer for quoted fields …
serhiy-storchaka Aug 11, 2026
53de65e
[3.10] gh-149698: Update bundled expat to 2.8.1 (GH-149699) (#155551)
StanFromIreland Aug 11, 2026
bba6648
[3.10] gh-152216: Update bundled expat to 2.8.2 (GH-152234) (#155577)
StanFromIreland Aug 11, 2026
33218ba
[3.10] gh-149018: Use `XML_SetHashSalt16Bytes` in `pyexpat`/`_element…
StanFromIreland Aug 13, 2026
4b39da7
[3.10] gh-155558: Update bundled Expat to 2.8.3 (GH-155560) (#155618)
StanFromIreland Aug 13, 2026
2dea9d8
[3.10] gh-145548: Use VMADDR_CID_LOCAL in VSOCK socket tests (GH-1455…
miss-islington Aug 13, 2026
d4d36ff
[3.10] gh-156723: Update bundled libexpat to version 2.8.4 (GH-156724…
StanFromIreland Sep 27, 2026
e12471f
[3.10] gh-157190: Fix tarfile `data`/`tar` filter bypass via hard lin…
freakboy3742 Sep 29, 2026
a202954
[3.10] gh-155694: Scope HTTPPasswordMgr credentials by URL scheme (GH…
miss-islington Oct 1, 2026
ab74e9e
[3.10] gh-156293: Use-after-free for server-side SSLContext with sni_…
gpshead Oct 1, 2026
a57751b
[3.10] gh-158446: Reject float format precision near INT_MAX (GH-1584…
gpshead Oct 1, 2026
bc08e44
[3.10] gh-157953: Update bundled Expat to 2.8.5 (GH-157957) (#158327)
StanFromIreland Oct 1, 2026
d0f7216
[3.10] gh-155292: Don't consider Unicode codepoint attributes outside…
encukou Oct 1, 2026
48a763a
[3.10] gh-156353: Fix configparser space delimiter parsing (GH-156382…
miss-islington Oct 1, 2026
078087f
[3.10] gh-157265: tarfile: Honor None result of filter for link fallb…
miss-islington Oct 1, 2026
9aecf9a
[3.10] gh-156002: Bound zipfile decompression for bzip2/LZMA/Zstandar…
miss-islington Oct 1, 2026
d322062
[3.10] gh-155999: `tarfile`: handle a member that leaves the destinat…
StanFromIreland Oct 1, 2026
cdbacb7
[3.10] gh-156793: Validate SSLContext.wrap_bio() parameters like wrap…
Yhg1s Oct 1, 2026
c00553d
[3.11] gh-87720 Fix additional header refolding-quoting edge case (GH…
miss-islington Oct 25, 2026
954fe5b
[3.11] gh-159428: Don't read mimetypes.knownfiles by default on Windo…
cjames23 Oct 25, 2026
8fc22f5
[3.11] gh-158876: Update bundled Expat to 2.9.0 (GH-158881) (#160261)
StanFromIreland Oct 25, 2026
4c152e5
[3.11] gh-160300: Reject cookies with a negative version in http.cook…
miss-islington Oct 25, 2026
937b4e6
[3.11] gh-160097: Reject links replacing the destination in `tarfile.…
miss-islington Oct 25, 2026
7a0e7df
[3.11] Add Sphinx markup for CVEs in Changelog entries (GH-159415) (#…
StanFromIreland Oct 25, 2026
32332b2
[3.11] gh-160040: Distrust compromised eMudhra intermediate CA keys (…
gpshead Oct 24, 2026
1f91fa4
[3.11] gh-160040: Add ssl eMudhra distrust entry to whatsnew (3.9.25.…
tiran Oct 24, 2026
0ccdf36
3.9.25.x: adapt backported tests to the 3.9 test.support API
icanhasmath Oct 27, 2026
88118a4
Upgrade bundled pip to 26.0.1.post1 (3.9.25.x)
icanhasmath Oct 27, 2026
2b21fed
Update version to 3.9.25.1 and add release notes
icanhasmath Oct 27, 2026
c516861
3.9.25.x: catch socket.timeout in the gh-119452 CGI read loop
icanhasmath Oct 27, 2026
5ef191a
[3.13] gh-143921: Reject NUL, CR and LF in IMAP commands (GH-143922, …
serhiy-storchaka Jul 7, 2026
e1e2dcf
gh-143923: Reject control characters in POP3 commands
sethmlarson Jan 20, 2026
18cd6aa
gh-150751: validate http.client Content-Length and chunk-size (GH-150…
metsw24-max Oct 8, 2026
efec30f
gh-150751: Ignore optional whitespace around Content-Length in http.c…
danilablagorodniy37 Oct 14, 2026
fe5c972
Release notes: imaplib, poplib and http.client fixes in 3.9.25.1
icanhasmath Oct 28, 2026
69cb071
Upgrade bundled setuptools to 82.0.1.post1 (3.9.25.x)
icanhasmath Oct 28, 2026
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
8 changes: 7 additions & 1 deletion Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@

extensions = ['sphinx.ext.coverage', 'sphinx.ext.doctest',
'pyspecific', 'c_annotations', 'escape4chm',
'asdl_highlight', 'peg_highlight']
'asdl_highlight', 'peg_highlight',
'sphinx.ext.extlinks']


doctest_global_setup = '''
Expand Down Expand Up @@ -239,3 +240,8 @@
# bpo-40204: Disable warnings on Sphinx 2 syntax of the C domain since the
# documentation is built with -W (warnings treated as errors).
c_warn_on_allowed_pre_v3 = False

# sphinx.ext.extlinks config
extlinks = {
'cve': ('https://www.cve.org/CVERecord?id=CVE-%s', 'CVE-%s'),
}
4 changes: 4 additions & 0 deletions Doc/library/asyncio-eventloop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ Opening network connections
.. versionchanged:: 3.5

Added support for SSL/TLS in :class:`ProactorEventLoop`.
.. versionchanged:: next
Raises a ``DeprecationWarning`` if ``ssl.check_hostname`` is ``True``
and ``server_hostname`` is not supplied. In Python 3.13 and
later a ``ValueError`` is raised instead.

.. seealso::

Expand Down
4 changes: 2 additions & 2 deletions Doc/library/http.cookies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ The following example demonstrates how to use the :mod:`http.cookies` module.
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"] = "/"
Expand Down
12 changes: 7 additions & 5 deletions Doc/library/os.path.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,17 @@ the :mod:`glob` module.)

.. function:: commonprefix(list)

Return the longest path prefix (taken character-by-character) that is a
prefix of all paths in *list*. If *list* is empty, return the empty string
Return the longest string prefix (taken character-by-character) that is a
prefix of all strings in *list*. If *list* is empty, return the empty string
(``''``).

.. note::
.. warning::

This function may return invalid paths because it works a
character at a time. To obtain a valid path, see
:func:`commonpath`.
character at a time.
If you need a **common path prefix**, then the algorithm
implemented in this function is not secure. Use
:func:`commonpath` for finding a common path prefix.

::

Expand Down
24 changes: 23 additions & 1 deletion Doc/library/ssl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,12 @@ to speed up repeated connections from the same clients.
:class:`SSLContext` representing a certificate chain that matches the server
name.

If the callback assigns a new context to :attr:`SSLSocket.context`, any
further ClientHello message on the same connection (for example after a
TLS 1.3 HelloRetryRequest) is dispatched to the new context's
*sni_callback*, if it has one; the original callback is not called again
for that connection.

Due to the early negotiation phase of the TLS connection, only limited
methods and attributes are usable like
:meth:`SSLSocket.selected_alpn_protocol` and :attr:`SSLSocket.context`.
Expand All @@ -1739,6 +1745,11 @@ to speed up repeated connections from the same clients.

.. versionadded:: 3.7

.. versionchanged:: next
After the callback assigns a new :attr:`SSLSocket.context`, later
ClientHello messages on the connection are dispatched to the new
context's *sni_callback*.

.. attribute:: SSLContext.set_servername_callback(server_name_callback)

This is a legacy API retained for backwards compatibility. When possible,
Expand Down Expand Up @@ -1856,7 +1867,11 @@ to speed up repeated connections from the same clients.
outgoing BIO.

The *server_side*, *server_hostname* and *session* parameters have the
same meaning as in :meth:`SSLContext.wrap_socket`.
same meaning as in :meth:`SSLContext.wrap_socket`, and are validated in
the same way: in particular a :exc:`DeprecationWarning` is raised when
:attr:`~SSLContext.check_hostname` is enabled but no *server_hostname* is
given, since there would be no name to match the peer's certificate
against. In Python 3.13 and later a ``ValueError`` is raised instead.

.. versionchanged:: 3.6
*session* argument was added.
Expand All @@ -1865,6 +1880,13 @@ to speed up repeated connections from the same clients.
The method returns on instance of :attr:`SSLContext.sslobject_class`
instead of hard-coded :class:`SSLObject`.

.. versionchanged:: next
The *server_side*, *server_hostname* and *session* parameters are now
validated as :meth:`SSLContext.wrap_socket` validates them. Previously
a context with :attr:`~SSLContext.check_hostname` enabled and no
*server_hostname* was accepted, and verified the certificate chain but
never the peer's identity.

.. attribute:: SSLContext.sslobject_class

The return type of :meth:`SSLContext.wrap_bio`, defaults to
Expand Down
13 changes: 13 additions & 0 deletions Doc/library/tarfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -950,14 +950,27 @@ reused in custom filters:
paths (in case the name is absolute
even after stripping slashes, e.g. ``C:/foo`` on Windows).
This raises :class:`~tarfile.AbsolutePathError`.
- Normalize filenames (:attr:`TarInfo.name`) that contain ``..`` components
using :func:`os.path.normpath`.
Note that this removes internal ``..`` components, which may change the
meaning of the name if it traverses symbolic links.
- :ref:`Refuse <tarfile-extraction-refuse>` to extract files whose absolute
path (after following symlinks) would end up outside the destination.
This raises :class:`~tarfile.OutsideDestinationError`.
- :ref:`Refuse <tarfile-extraction-refuse>` to extract links (hard or soft)
whose name refers to the destination directory itself.
This raises :class:`~tarfile.OutsideDestinationError`.
Note that such files are refused even on platforms that do not support
symbolic links.
- Clear high mode bits (setuid, setgid, sticky) and group/other write bits
(:attr:`~stat.S_IWGRP`|:attr:`~stat.S_IWOTH`).

Return the modified ``TarInfo`` member.

.. versionchanged:: next

Filenames containing ``..`` components are now normalized.

.. function:: data_filter(/, member, path)

Implements the ``'data'`` filter.
Expand Down
10 changes: 8 additions & 2 deletions Doc/library/urllib.request.rst
Original file line number Diff line number Diff line change
Expand Up @@ -917,8 +917,14 @@ These methods are available on :class:`HTTPPasswordMgr` and

*uri* can be either a single URI, or a sequence of URIs. *realm*, *user* and
*passwd* must be strings. This causes ``(user, passwd)`` to be used as
authentication tokens when authentication for *realm* and a super-URI of any of
the given URIs is given.
authentication tokens when authentication for *realm* and a super-URI of any
of the given URIs is given. If a URI includes a scheme, its credentials only
match authentication URIs with the same scheme or no scheme. A URI without a
scheme matches authentication URIs with any scheme.

.. versionchanged:: next
Authentication credentials for URIs with a scheme are now scoped by
that scheme.


.. method:: HTTPPasswordMgr.find_user_password(realm, authuri)
Expand Down
5 changes: 5 additions & 0 deletions Doc/library/wsgiref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

--------------

.. warning::

:mod:`wsgiref` is a reference implementation and is not recommended for
production. The module only implements basic security checks.

The Web Server Gateway Interface (WSGI) is a standard interface between web
server software and web applications written in Python. Having a standard
interface makes it easy to use an application that supports WSGI with a number
Expand Down
2 changes: 2 additions & 0 deletions Doc/tools/extensions/pyspecific.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ def run(self):

issue_re = re.compile('(?:[Ii]ssue #|bpo-)([0-9]+)', re.I)
gh_issue_re = re.compile('(?:gh-issue-|gh-)([0-9]+)', re.I)
cve_re = re.compile('CVE-([0-9]{4}-[0-9]{4,})', re.I)
whatsnew_re = re.compile(r"(?im)^what's new in (.*?)\??$")


Expand Down Expand Up @@ -444,6 +445,7 @@ def run(self):
content = issue_re.sub(r':issue:`\1`', content)
# Fallback handling for the GitHub issue
content = gh_issue_re.sub(r':gh:`\1`', content)
content = cve_re.sub(r':cve:`\1`', content)
content = whatsnew_re.sub(r'\1', content)
# remove first 3 lines as they are the main heading
lines = ['.. default-role:: obj', ''] + content.splitlines()[3:]
Expand Down
6 changes: 3 additions & 3 deletions Doc/using/windows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,9 @@ on using nuget. What follows is a summary that is sufficient for Python
developers.

The ``nuget.exe`` command line tool may be downloaded directly from
``https://aka.ms/nugetclidl``, for example, using curl or PowerShell. With the
tool, the latest version of Python for 64-bit or 32-bit machines is installed
using::
``https://dist.nuget.org/win-x86-commandline/latest/nuget.exe``, for example,
using curl or PowerShell. With the tool, the latest version of Python for
64-bit or 32-bit machines is installed using::

nuget.exe install python -ExcludeVersion -OutputDirectory .
nuget.exe install pythonx86 -ExcludeVersion -OutputDirectory .
Expand Down
124 changes: 124 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1697,3 +1697,127 @@ tarfile
:func:`~tarfile.TarFile.errorlevel` is zero.
(Contributed by Matt Prodani and Petr Viktorin in :gh:`112887`
and CVE 2025-4435.)


Notable changes in 3.9.25.1
===========================

This is an ActiveState security release of the 3.9 line, which is past
its upstream end of life.

It carries the security fixes released upstream in Python 3.10.20,
3.10.21, 3.10.22 and 3.11.18 that apply to 3.9, on top of 3.9.25, plus
three fixes that upstream released only for newer lines (or has not
released yet): the :mod:`imaplib`, :mod:`poplib` and :mod:`http.client`
response-framing items below. The full list of changes is in the
changelog; the notable ones are below.

ssl
---

* The :mod:`ssl` module now rejects TLS certificate chains that contain one
of a set of compromised eMudhra intermediate CA certificates. The affected
certificates are identified by their public key, so cross-signed copies that
reuse the same key are blocked as well. It is a defense-in-depth backstop
that applies even when an application supplies its own root CA bundle, and
regardless of whether the platform trust store has removed trust.
(Contributed by Christian Heimes in :gh:`160040` for CVE 2026-115557.)

ensurepip
---------

* The bundled ``pip`` is upgraded from 23.0.1 to 26.0.1.post1, the ActiveState
security release of pip 26.0.1 (the last pip that supports Python 3.9).
pip loads its own vendored ``certifi`` CA bundle in addition to the system
trust store; the bundle in 26.0.1.post1 (certifi 2026.10.19) drops the
compromised eMudhra emSign root, and the release also patches
CVE-2026-3219, CVE-2026-6357, CVE-2026-8643 and CVE-2026-13346.
* The bundled ``setuptools`` is upgraded from 79.0.1 to 82.0.1.post1, the
ActiveState security release of setuptools 82.0.1 (the last setuptools that
supports Python 3.9), fixing CVE-2026-59890. setuptools removed
``pkg_resources`` in 82.0.0, so environments seeded by :mod:`ensurepip` or
:mod:`venv` no longer include it; install an older setuptools if an
application still imports it.

tarfile
-------

* The ``data`` and ``tar`` extraction filters reject several more path and
link escapes: hard links to symbolic links (:gh:`157190`), symlinks created
through the hard-link extraction fallback (:gh:`151558`), members whose name
leaves the destination and comes back (:gh:`155999`), link targets that
differ from the value written to disk (:gh:`149486`), and links that replace
the destination directory itself (:gh:`160097`, CVE 2026-114583).
* :meth:`~tarfile.TarFile.extract` applies the filter to link fallbacks and
honors a ``None`` result from it (:gh:`151987`, :gh:`157265`).

http, email, urllib and wsgiref
-------------------------------

* Control characters are rejected in :mod:`http.cookies` morsels
(:gh:`143919`, :gh:`145599`), ``data:`` URL media types (:gh:`143925`),
:mod:`wsgiref` headers and status lines (:gh:`143916`, :gh:`144370`) and
HTTP tunnel headers (:gh:`146211`).
* :mod:`http.client` bounds memory use for large responses (:gh:`119451`) and
limits trailer lines and interim responses (:gh:`150743`); :mod:`http.server`
gets the same bound for CGI on Windows (:gh:`119452`).
* :class:`~urllib.request.HTTPPasswordMgr` credentials are scoped by URL
scheme (:gh:`155694`, CVE 2026-15806).
* :mod:`email` refuses to write unsafely folded headers (:gh:`144125`) and
folds comments correctly (:gh:`143935`, :gh:`87720`).
* :class:`http.cookiejar.DefaultCookiePolicy` checks the domain of cookies
with a negative ``Version`` (:gh:`160300`).
* :mod:`http.client` only accepts a ``Content-Length`` and chunk sizes that
match the HTTP grammar; signs, underscores and ``0x`` prefixes are no
longer accepted (:gh:`150751`, CVE 2026-103995).
* :mod:`imaplib` rejects NUL, CR and LF in command arguments (:gh:`143921`,
CVE 2025-15366) and :mod:`poplib` rejects control characters in commands
(:gh:`143923`, CVE 2025-15367), which could be used to inject extra
commands.

XML
---

* The bundled libexpat is updated from 2.7.3 to 2.9.0.
* :mod:`xml.parsers.expat` seeds expat's hash with 16 bytes of entropy when
available (:gh:`149018`) and no longer crashes on deeply nested content
models (:gh:`145986`).
* Quadratic behavior is removed from :mod:`xml.dom.minidom` (:gh:`142145`)
and :mod:`xml.etree.ElementTree` path predicates (:gh:`152674`).

Denial-of-service and memory-safety fixes
-----------------------------------------

* Quadratic or exponential time is removed from :class:`html.parser.HTMLParser`
(:gh:`153030`), :mod:`configparser` (:gh:`146333`), :class:`csv.Sniffer`
(:gh:`109638`, :gh:`98820`), :func:`unicodedata.normalize` (:gh:`149079`)
and :mod:`plistlib` (:gh:`119342`).
* :mod:`zipfile` bounds decompression per read for bzip2 and LZMA members
(:gh:`156002`).
* Use-after-free and overflow fixes in :mod:`ssl` (:gh:`144833`,
:gh:`156293`), :mod:`bz2` and :mod:`lzma` (:gh:`148395`, :gh:`150599`) and
:class:`float` / :class:`complex` formatting (:gh:`158446`).

Other
-----

* ``SourcelessFileLoader`` opens ``.pyc`` files with :func:`io.open_code`
(:gh:`145506`, CVE 2026-2297).
* :mod:`webbrowser` rejects URLs starting with a dash (:gh:`143930`,
:gh:`148169`) and runs ``osascript`` by absolute path (:gh:`137586`).
* :mod:`mimetypes` no longer reads :data:`mimetypes.knownfiles` by default on
Windows (:gh:`159428`).
* :mod:`shutil.unpack_archive` no longer writes outside the destination for
some ZIP files on Windows (:gh:`146581`).
* :mod:`configparser` normalizes line endings in multi-line values
(:gh:`143927`).
* :mod:`stringprep` and the ``idna`` codec stop using Unicode attributes beyond
:rfc:`3454` (:gh:`155292`).
* :func:`ssl.SSLContext.wrap_bio` and :mod:`asyncio` TLS methods validate
their arguments like :meth:`~ssl.SSLContext.wrap_socket` (:gh:`156793`).
* ``ftplib.ftpcp`` no longer trusts the IPv4 address in a PASV reply
(:gh:`87451`, the CVE-2021-4189 fix).

Not included: the expat amplification-tuning API from :gh:`90949`. The
protection itself (CVE-2025-59375) is built into libexpat 2.7.2 and later
and is on by default, so 3.9 gets it from the bundled libexpat 2.9.0.
2 changes: 1 addition & 1 deletion Include/patchlevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define PY_RELEASE_SERIAL 0

/* Version as a string */
#define PY_VERSION "3.9.25"
#define PY_VERSION "3.9.25.1"
/*--end constants--*/

/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
Expand Down
3 changes: 3 additions & 0 deletions Include/pyexpat.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ struct PyExpat_CAPI
int (*SetHashSalt)(XML_Parser parser, unsigned long hash_salt);
/* might be NULL for expat < 2.6.0 */
XML_Bool (*SetReparseDeferralEnabled)(XML_Parser parser, XML_Bool enabled);
/* might be NULL for expat < 2.8.0 */
XML_Bool (*SetHashSalt16Bytes)(
XML_Parser parser, const uint8_t entropy[16]);
/* always add new stuff to the end! */
};

8 changes: 5 additions & 3 deletions Include/pyhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t);
* pppppppp ssssssss ........ fnv -- two Py_hash_t
* k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t
* ........ ........ ssssssss djbx33a -- 16 bytes padding + one Py_hash_t
* ........ ........ eeeeeeee pyexpat XML hash salt
* eeeeeeee eeeeeeee eeeeeeee pyexpat XML hash salt
*
* memory layout on 32 bit systems
* cccccccc cccccccc cccccccc uc
* ppppssss ........ ........ fnv -- two Py_hash_t
* k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t (*)
* ........ ........ ssss.... djbx33a -- 16 bytes padding + one Py_hash_t
* ........ ........ eeee.... pyexpat XML hash salt
* eeeeeeee eeeeeeee eeee.... pyexpat XML hash salt
*
* (*) The siphash member may not be available on 32 bit platforms without
* an unsigned int64 data type.
Expand All @@ -72,7 +72,9 @@ typedef union {
Py_hash_t suffix;
} djbx33a;
struct {
unsigned char padding[16];
/* 16 bytes for XML_SetHashSalt16Bytes */
uint8_t hashsalt16[16];
/* 4/8 bytes for legacy XML_SetHashSalt */
Py_hash_t hashsalt;
} expat;
} _Py_HashSecret_t;
Expand Down
Loading
Loading