diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 97c1078022601b1..8fab7246b1f89dc 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -418,6 +418,10 @@ Opening network connections .. versionchanged:: 3.5 Added support for SSL/TLS in :class:`ProactorEventLoop`. + .. versionchanged:: 3.7.17.8 + 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:: diff --git a/Doc/library/email.errors.rst b/Doc/library/email.errors.rst index f4b9f52509689ea..878c09bb0402f7f 100644 --- a/Doc/library/email.errors.rst +++ b/Doc/library/email.errors.rst @@ -59,6 +59,12 @@ The following exception classes are defined in the :mod:`email.errors` module: :class:`~email.mime.image.MIMEImage`). +.. exception:: HeaderWriteError() + + Raised when an error occurs when the :mod:`~email.generator` outputs + headers. + + Here is the list of the defects that the :class:`~email.parser.FeedParser` can find while parsing messages. Note that the defects are added to the message where the problem was found, so for example, if a message nested inside a diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst index 8e7076259810f55..34231597d22d7a1 100644 --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -229,6 +229,24 @@ added matters. To illustrate:: .. versionadded:: 3.6 + + .. attribute:: verify_generated_headers + + If ``True`` (the default), the generator will raise + :exc:`~email.errors.HeaderWriteError` instead of writing a header + that is improperly folded or delimited, such that it would + be parsed as multiple headers or joined with adjacent data. + Such headers can be generated by custom header classes or bugs + in the ``email`` module. + + As it's a security feature, this defaults to ``True`` even in the + :class:`~email.policy.Compat32` policy. + For backwards compatible, but unsafe, behavior, it must be set to + ``False`` explicitly. + + .. versionadded:: 3.7.17.8 + + The following :class:`Policy` method is intended to be called by code using the email library to create policy instances with custom settings: diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst index ac844a683bf7ac1..0ee31c09f54831d 100644 --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -15,14 +15,18 @@ This module defines a class :class:`HTMLParser` which serves as the basis for parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML. -.. class:: HTMLParser(*, convert_charrefs=True) +.. class:: HTMLParser(*, convert_charrefs=True, scripting=False) Create a parser instance able to parse invalid markup. - If *convert_charrefs* is ``True`` (the default), all character - references (except the ones in ``script``/``style`` elements) are + If *convert_charrefs* is true (the default), all character + references (except the ones in elements like ``script`` and ``style``) are automatically converted to the corresponding Unicode characters. + If *scripting* is false (the default), the content of the ``noscript`` + element is parsed normally; if it's true, it's returned as is without + being parsed. + An :class:`.HTMLParser` instance is fed HTML data and calls handler methods when start tags, end tags, text, comments, and other markup elements are encountered. The user should subclass :class:`.HTMLParser` and override its @@ -37,6 +41,9 @@ parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML. .. versionchanged:: 3.5 The default value for argument *convert_charrefs* is now ``True``. + .. versionchanged:: 3.7.17.8 + Added the *scripting* parameter. + Example HTML Parser Application ------------------------------- @@ -159,15 +166,15 @@ implementations do nothing (except for :meth:`~HTMLParser.handle_startendtag`): .. method:: HTMLParser.handle_data(data) This method is called to process arbitrary data (e.g. text nodes and the - content of ```` and ````). + content of elements like ``script`` and ``style``). .. method:: HTMLParser.handle_entityref(name) This method is called to process a named character reference of the form ``&name;`` (e.g. ``>``), where *name* is a general entity reference - (e.g. ``'gt'``). This method is never called if *convert_charrefs* is - ``True``. + (e.g. ``'gt'``). + This method is only called if *convert_charrefs* is false. .. method:: HTMLParser.handle_charref(name) @@ -175,8 +182,8 @@ implementations do nothing (except for :meth:`~HTMLParser.handle_startendtag`): This method is called to process decimal and hexadecimal numeric character references of the form ``&#NNN;`` and ``&#xNNN;``. For example, the decimal equivalent for ``>`` is ``>``, whereas the hexadecimal is ``>``; - in this case the method will receive ``'62'`` or ``'x3E'``. This method - is never called if *convert_charrefs* is ``True``. + in this case the method will receive ``'62'`` or ``'x3E'``. + This method is only called if *convert_charrefs* is false. .. method:: HTMLParser.handle_comment(data) @@ -284,8 +291,8 @@ Parsing an element with a few attributes and a title:: Data : Python End tag : h1 -The content of ``script`` and ``style`` elements is returned as is, without -further parsing:: +The content of elements like ``script`` and ``style`` is returned as is, +without further parsing:: >>> parser.feed('') Start tag: style @@ -294,10 +301,10 @@ further parsing:: End tag : style >>> parser.feed('') + ... 'alert("hello! ☺");') Start tag: script attr: ('type', 'text/javascript') - Data : alert("hello!"); + Data : alert("hello! ☺"); End tag : script Parsing comments:: @@ -317,7 +324,7 @@ correct char (note: these 3 references are all equivalent to ``'>'``):: Feeding incomplete chunks to :meth:`~HTMLParser.feed` works, but :meth:`~HTMLParser.handle_data` might be called more than once -(unless *convert_charrefs* is set to ``True``):: +if *convert_charrefs* is false:: >>> for chunk in ['buff', 'ered ', 'text']: ... parser.feed(chunk) diff --git a/Doc/library/http.cookies.rst b/Doc/library/http.cookies.rst index 01bedfd266a8d57..30190ee4cd463c0 100644 --- a/Doc/library/http.cookies.rst +++ b/Doc/library/http.cookies.rst @@ -262,9 +262,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"] = "/" diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst index 1dfa2ec073313b8..581cf73c4c2c1e0 100644 --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -104,8 +104,7 @@ write code that handles both IP versions correctly. Address objects are 1. A string in decimal-dot notation, consisting of four decimal integers in the inclusive range 0--255, separated by dots (e.g. ``192.168.0.1``). Each integer represents an octet (byte) in the address. Leading zeroes are - tolerated only for values less than 8 (as there is no ambiguity - between the decimal and octal interpretations of such strings). + not tolerated to prevent confusion with octal notation. 2. An integer that fits into 32 bits. 3. An integer packed into a :class:`bytes` object of length 4 (most significant octet first). @@ -117,6 +116,22 @@ write code that handles both IP versions correctly. Address objects are >>> ipaddress.IPv4Address(b'\xC0\xA8\x00\x01') IPv4Address('192.168.0.1') + .. versionchanged:: 3.8 + + Leading zeros are tolerated, even in ambiguous cases that look like + octal notation. + + .. versionchanged:: 3.10 + + Leading zeros are no longer tolerated and are treated as an error. + IPv4 address strings are now parsed as strict as glibc + :func:`~socket.inet_pton`. + + .. versionchanged:: 3.7.17.8 + + The above change is also included in ActiveState Python 3.7 + starting with version 3.7.17.8. + .. attribute:: version The appropriate version number: ``4`` for IPv4, ``6`` for IPv6. diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 685d5608f7fbfcc..9ef668cbf41d4f6 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1833,6 +1833,10 @@ features: platform-dependent. On some platforms, they are ignored and you should call :func:`chmod` explicitly to set them. + On Windows, a *mode* of ``0o700`` is specifically handled to apply access + control to the new directory such that only the current user and + administrators have access. Other values of *mode* are ignored. + This function can also support :ref:`paths relative to directory descriptors `. @@ -1845,6 +1849,9 @@ features: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. + .. versionchanged:: 3.7.17.8 + Windows now handles a *mode* of ``0o700``. + .. function:: makedirs(name, mode=0o777, exist_ok=False) diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst index e43b9aecd86835a..efe931a8d6082f5 100644 --- a/Doc/library/pyexpat.rst +++ b/Doc/library/pyexpat.rst @@ -196,6 +196,42 @@ XMLParser Objects :exc:`ExpatError` to be raised with the :attr:`code` attribute set to ``errors.codes[errors.XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING]``. +.. method:: xmlparser.SetReparseDeferralEnabled(enabled) + + .. warning:: + + Calling ``SetReparseDeferralEnabled(False)`` has security implications, + as detailed below; please make sure to understand these consequences + prior to using the ``SetReparseDeferralEnabled`` method. + + Expat 2.6.0 introduced a security mechanism called "reparse deferral" + where instead of causing denial of service through quadratic runtime + from reparsing large tokens, reparsing of unfinished tokens is now delayed + by default until a sufficient amount of input is reached. + Due to this delay, registered handlers may — depending of the sizing of + input chunks pushed to Expat — no longer be called right after pushing new + input to the parser. Where immediate feedback and taking over responsiblity + of protecting against denial of service from large tokens are both wanted, + calling ``SetReparseDeferralEnabled(False)`` disables reparse deferral + for the current Expat parser instance, temporarily or altogether. + Calling ``SetReparseDeferralEnabled(True)`` allows re-enabling reparse + deferral. + + Note that :meth:`SetReparseDeferralEnabled` has been backported to some + prior releases of CPython as a security fix. Check for availability of + :meth:`SetReparseDeferralEnabled` using :func:`hasattr` if used in code + running across a variety of Python versions. + + .. versionadded:: 3.7.17.8 + +.. method:: xmlparser.GetReparseDeferralEnabled() + + Returns whether reparse deferral is currently enabled for the given + Expat parser instance. + + .. versionadded:: 3.7.17.8 + + :class:`xmlparser` objects have the following attributes: diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 0646b30f6f59458..96887f99c28380d 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1699,6 +1699,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`. @@ -1722,6 +1728,11 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.7 + .. versionchanged:: 3.7.17.8 + 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, @@ -1839,7 +1850,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. @@ -1848,6 +1863,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:: 3.7.17.8 + 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 diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 2610fe3a683f01d..f99682dfa3f73c5 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -230,6 +230,15 @@ The :mod:`tarfile` module defines the following exceptions: Raised to refuse extracting a symbolic link pointing outside the destination directory. +.. exception:: LinkFallbackError + + Raised to refuse emulating a link (hard or symbolic) by extracting another + archive member, when that member would be rejected by the filter location. + The exception that was raised to reject the replacement member is available + as :attr:`!BaseException.__context__`. + + .. versionadded:: 3.7.17.8 + The following constants are available at the module level: @@ -713,6 +722,11 @@ A ``TarInfo`` object has the following public data attributes: Name of the target file name, which is only present in :class:`TarInfo` objects of type :const:`LNKTYPE` and :const:`SYMTYPE`. + For symbolic links (``SYMTYPE``), the *linkname* is relative to the directory + that contains the link. + For hard links (``LNKTYPE``), the *linkname* is relative to the root of + the archive. + .. attribute:: TarInfo.uid @@ -912,19 +926,38 @@ 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 ` to extract files whose absolute path (after following symlinks) would end up outside the destination. This raises :class:`~tarfile.OutsideDestinationError`. + - :ref:`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:: 3.7.17.8 + + Filenames containing ``..`` components are now normalized. + .. function:: data_filter(/, member, path) Implements the ``'data'`` filter. In addition to what ``tar_filter`` does: + - Normalize link targets (:attr:`TarInfo.linkname`) using + :func:`os.path.normpath`. + Note that this removes internal ``..`` components, which may change the + meaning of the link if the path in :attr:`!TarInfo.linkname` traverses + symbolic links. + - :ref:`Refuse ` to extract links (hard or soft) that link to absolute paths, or ones that link outside the destination. @@ -953,6 +986,10 @@ reused in custom filters: Return the modified ``TarInfo`` member. + .. versionchanged:: 3.7.17.8 + + Link targets are now normalized. + .. _tarfile-extraction-refuse: @@ -979,6 +1016,7 @@ Here is an incomplete list of things to consider: * Extract to a :func:`new temporary directory ` to prevent e.g. exploiting pre-existing links, and to make it easier to clean up after a failed extraction. +* Disallow symbolic links if you do not need the functionality. * When working with untrusted data, use external (e.g. OS-level) limits on disk, memory and CPU usage. * Check filenames against an allow-list of characters diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 22bad2dc6a2ebdc..ffbdc2ab0e5783c 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -916,8 +916,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:: 3.7.17.8 + Authentication credentials for URIs with a scheme are now scoped by + that scheme. .. method:: HTTPPasswordMgr.find_user_password(realm, authuri) diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index ec38f09f76de091..91dea142d039ecf 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -163,6 +163,11 @@ data but would still like to have incremental parsing capabilities, take a look at :func:`iterparse`. It can be useful when you're reading a large XML document and don't want to hold it wholly in memory. +Where *immediate* feedback through events is wanted, calling method +:meth:`XMLPullParser.flush` can help reduce delay; +please make sure to study the related security notes. + + Finding interesting elements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1174,6 +1179,24 @@ XMLParser Objects Feeds data to the parser. *data* is encoded data. + + .. method:: flush() + + Triggers parsing of any previously fed unparsed data, which can be + used to ensure more immediate feedback, in particular with Expat >=2.6.0. + The implementation of :meth:`flush` temporarily disables reparse deferral + with Expat (if currently enabled) and triggers a reparse. + Disabling reparse deferral has security consequences; please see + :meth:`xml.parsers.expat.xmlparser.SetReparseDeferralEnabled` for details. + + Note that :meth:`flush` has been backported to some prior releases of + CPython as a security fix. Check for availability of :meth:`flush` + using :func:`hasattr` if used in code running across a variety of Python + versions. + + .. versionadded:: 3.7.17.8 + + :meth:`XMLParser.feed` calls *target*\'s ``start(tag, attrs_dict)`` method for each opening tag, its ``end(tag)`` method for each closing tag, and data is processed by method ``data(data)``. :meth:`XMLParser.close` calls @@ -1234,6 +1257,22 @@ XMLPullParser Objects Feed the given bytes data to the parser. + .. method:: flush() + + Triggers parsing of any previously fed unparsed data, which can be + used to ensure more immediate feedback, in particular with Expat >=2.6.0. + The implementation of :meth:`flush` temporarily disables reparse deferral + with Expat (if currently enabled) and triggers a reparse. + Disabling reparse deferral has security consequences; please see + :meth:`xml.parsers.expat.xmlparser.SetReparseDeferralEnabled` for details. + + Note that :meth:`flush` has been backported to some prior releases of + CPython as a security fix. Check for availability of :meth:`flush` + using :func:`hasattr` if used in code running across a variety of Python + versions. + + .. versionadded:: 3.7.17.8 + .. method:: close() Signal the parser that the data stream is terminated. Unlike diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 819d3e830749882..03ddb6b255f873a 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -360,9 +360,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 . diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 968c2e8f11a551f..85376613cfa22a7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2730,3 +2730,214 @@ CVE-2024-9287 In CPython's venv module, improper quoting of path names during virtual environment creation allows for command injection into activation scripts (e.g., source venv/bin/activate). This vulnerability enables attackers to execute arbitrary commands when such a virtual environment is activated. Virtual environments not created by an attacker or not activated before use are unaffected. starwindsoftware.com+2 + +Notable changes in 3.7.17.8 +=========================== + +This is an ActiveState security release of the 3.7 line, which is past its +upstream end of life. It carries the security fixes that upstream released +for Python 3.8 through 3.11 since 3.7.17 and that apply to 3.7, and that +3.7.17.7 did not already have. Most are ports of the commits on the +ActiveState 3.9.25.x line. 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.) +* An empty list is no longer accepted by + :meth:`~ssl.SSLContext.set_npn_protocols` (:gh:`121227`, CVE 2024-5642). +* Use-after-free fixes for a server-side context with an SNI callback + (:gh:`156293`, CVE 2026-19445) and when ``SSL_new()`` fails (:gh:`144833`). +* :meth:`~ssl.SSLContext.wrap_bio` validates its arguments like + :meth:`~ssl.SSLContext.wrap_socket` (:gh:`156793`, CVE 2026-19553). + +ensurepip +--------- + +* The bundled ``pip`` is upgraded from 23.0.1 to 24.0.post4, the ActiveState + security release of pip 24.0 (the last pip that supports Python 3.7). pip + loads its own vendored ``certifi`` CA bundle in addition to the system trust + store; its bundle (certifi 2026.10.23) drops the emSign ECC + Root CA - G3, emSign Root CA - C1 and emSign ECC Root CA - C3 roots of the + compromised eMudhra/emSign CA, leaving emSign Root CA - G1 as the only + emSign root. The release also fixes CVE-2023-5752, CVE-2025-8869, + CVE-2026-1703, CVE-2026-3219, CVE-2026-6357, CVE-2026-8643 and + CVE-2026-13346. Its vendored urllib3 (ActiveState 1.26.20.post4) fixes + CVE-2023-45803, CVE-2024-37891, CVE-2025-50181, CVE-2025-66418, + CVE-2025-66471, CVE-2026-21441, CVE-2026-44431, CVE-2026-97687 and + CVE-2026-97689, and its vendored requests 2.31.0 carries the fixes for + CVE-2024-47081 and CVE-2026-25645. +* The bundled ``setuptools`` is upgraded from 47.1.0 to 68.0.0.post3, the + ActiveState security release of setuptools 68.0.0 (the last setuptools that + supports Python 3.7), fixing CVE-2022-40897, CVE-2024-6345, CVE-2025-47273, + CVE-2026-59890 and GHSA-xmj3-9gf7-h52w. setuptools 68 replaces :mod:`distutils` with its own copy + when it is imported; a process that imports ``pip`` before ``setuptools`` + can fail with an ``AssertionError`` about ``distutils/core.py``. Import + ``setuptools`` first, or set ``SETUPTOOLS_USE_DISTUTILS=stdlib``. + +tarfile and shutil +------------------ + +* The ``data`` and ``tar`` extraction filters normalize link targets and + reject the escapes reported in CVE 2024-12718, CVE 2025-4138, + CVE 2025-4330, CVE 2025-4435 and CVE 2025-4517 (:gh:`135034`), plus 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`), links that replace the destination + directory itself (:gh:`160097`) and symlinks relative to their own directory + (:gh:`107845`). +* :meth:`~tarfile.TarFile.extract` applies the filter to link fallbacks and + honors a ``None`` result from it (:gh:`151987`, :gh:`157265`). +* Archives with negative member offsets are rejected (:gh:`130577`, + CVE 2025-8194), GNU long names no longer change a member's type + (:gh:`141707`), and reading a stream past its end terminates + (:gh:`151981`). +* Extracting a symlink over an existing file replaces it instead of falling + back to copying the link target (bpo-12800). +* :func:`os.path.realpath` gains a *strict* parameter, including the new + :data:`os.path.ALLOW_MISSING` value used by the filters. +* On Windows, :func:`os.path.realpath` now resolves symbolic links and + junctions, as it does from Python 3.8 on (bpo-9949). Before this + release it returned the unresolved absolute path, so the extraction + filters could not see symlinks pointing outside the destination; that + bypass also affected 3.7.17.7. This is a behavior change for any + caller of :func:`~os.path.realpath` on Windows. +* :func:`shutil.unpack_archive` no longer writes outside the destination for + some ZIP files on Windows (:gh:`146581`). + +tempfile +-------- + +* Cleanup of :class:`tempfile.TemporaryDirectory` no longer follows symlinks + out of the directory (:gh:`91133`, CVE 2023-6597), no longer resolves paths + again when it recovers from a permission error (:gh:`157579`, + CVE 2026-12345), and reports the original :exc:`PermissionError` on + Windows (bpo-43153, :gh:`79325`). +* On Windows, ``os.mkdir(path, 0o700)`` creates a directory that only the + owner, SYSTEM and Administrators can access, which makes + :func:`tempfile.mkdtemp` private (:gh:`118486`, CVE 2024-4030). + +http, email, urllib and wsgiref +------------------------------- + +* :func:`urllib.parse.urlsplit` rejects bracketed hosts that are not IPv6 or + IPvFuture addresses and square brackets elsewhere in the host + (:gh:`103848`, :gh:`105704`; CVE 2024-11168, CVE 2025-0938). +* 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`), HTTP + tunnel headers (:gh:`146211`), :mod:`imaplib` command arguments + (:gh:`143921`) and :mod:`poplib` commands (:gh:`143923`). +* :mod:`http.client` bounds memory use for large responses (:gh:`119451`), + limits trailer lines and interim responses (:gh:`150743`) and only accepts a + ``Content-Length`` and chunk sizes that match the HTTP grammar + (:gh:`150751`); :mod:`http.server` gets the same bound for CGI + (:gh:`119452`). +* :class:`~urllib.request.HTTPPasswordMgr` credentials are scoped by URL + scheme (:gh:`155694`). +* :mod:`email` encodes newlines in headers and refuses to write unsafely + folded headers (:gh:`121650`, :gh:`144125`), keeps list separators plain + when folding address lists (:gh:`80222`, :gh:`121284`, CVE 2025-1795) and + folds comments correctly (:gh:`143935`, :gh:`87720`). +* :class:`http.cookiejar.DefaultCookiePolicy` checks the domain of cookies + with a negative ``Version`` (:gh:`160300`). +* The pure-Python :func:`socket.socketpair` fallback authenticates the + connection (:gh:`122133`, CVE 2024-3219). + +ipaddress +--------- + +* Leading zeros in IPv4 address octets are rejected, as in Python 3.8.12 and + later, because they are ambiguous with octal notation (bpo-36384, + CVE 2021-29921). This is a behavior change: ``"010.0.0.1"`` now raises + :exc:`ValueError`. +* IPv6 address parsing is bounded (:gh:`128840`), and the properties of + IPv4-mapped IPv6 addresses match the IPv4 address (:gh:`122792`). +* :class:`~ipaddress.IPv4Network` and :class:`~ipaddress.IPv6Network` hash + the network address and netmask as a pair, so overlapping networks no + longer collide (:gh:`134062`). + +XML and HTML +------------ + +* The bundled libexpat is updated from 2.6.4 to 2.9.0. +* :mod:`xml.parsers.expat` exposes the reparse deferral API added in libexpat + 2.6.0 (:meth:`!SetReparseDeferralEnabled`, :meth:`!GetReparseDeferralEnabled` + and :meth:`xml.etree.ElementTree.XMLPullParser.flush`), seeds expat's hash + with 16 bytes of entropy when available (:gh:`149018`), keeps parent + parsers alive while subparsers use them (:gh:`139400`) and no longer + crashes on deeply nested content models (:gh:`145986`). +* :class:`html.parser.HTMLParser` follows HTML5 for comments, tags, CDATA + sections and the ``script``, ``style``, ``textarea`` and ``title`` elements, + and loses its quadratic cases (:gh:`135661`, :gh:`102555`, :gh:`118350`, + :gh:`135462`, :gh:`153030`). The ``xmp``, ``iframe``, ``noembed``, + ``noframes`` and ``plaintext`` elements, and ``noscript`` when the new + *scripting* argument is true, are parsed as raw text too (:gh:`137836`). +* 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 :mod:`configparser` + (:gh:`146333`, :gh:`156353`), :class:`csv.Sniffer` (:gh:`109638`, + :gh:`98820`), :func:`unicodedata.normalize` (:gh:`149079`), + :func:`os.path.expandvars` (:gh:`136065`), the :mod:`email` parameter parser + (:gh:`136063`), :mod:`imaplib` (:gh:`119511`) and :mod:`plistlib` + (:gh:`119342`). +* :mod:`zipfile` rejects "quoted-overlap" zip bombs (:gh:`109858`), checks the + ZIP64 end of central directory record (:gh:`139700`) and bounds + decompression per read for bzip2 and LZMA members (:gh:`156002`). +* Use-after-free and out-of-bounds fixes in the ``unicode-escape`` decoder + (:gh:`133767`, CVE 2025-4516), :mod:`bz2` and :mod:`lzma` (:gh:`148395`, + :gh:`150599`), the ``iso2022_jp_3`` and ``iso2022_jp_2004`` codecs + (:gh:`101180`), :class:`float` / :class:`complex` formatting + (:gh:`158446`), and :class:`list` comparison and slice assignment when an + operand changes the list (:gh:`120298`, :gh:`120384`). + +Other +----- + +* :mod:`site` skips hidden ``.pth`` files (:gh:`113659`). +* CVE 2022-42919 (:gh:`97514`, Linux abstract sockets in + :mod:`multiprocessing`) does not affect 3.7: its ``AF_UNIX`` listeners have + always used filesystem paths. The changelog entry records that. +* :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:`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`). +* ``ftplib.ftpcp`` no longer trusts the IPv4 address in a PASV reply + (:gh:`87451`, the CVE-2021-4189 fix). +* ``ssl.SSLContext.load_verify_locations(cadata=...)`` detects the end of DER + data with OpenSSL 3 (:gh:`100372`). + +Build +----- + +* Windows release builds link with ``/OPT:REF,NOICF`` (bpo-42825). With + identical COMDAT folding, newer MSVC linkers merge ``wrap_binaryfunc`` and + ``wrap_binaryfunc_l`` in ``Objects/typeobject.c``, and ``subclass + x`` + then returns ``NotImplemented`` instead of raising :exc:`TypeError` for + subclasses of built-in types. + +* On Windows, the core links the zlib import library as ``z.lib`` when the + zlib directory provides one (the ActiveState ``shared/zlib`` 1.3.2 and + later), and as ``zlib.lib`` otherwise. + +Not included, because they do not apply to 3.7: fixes for code that only +exists in later versions (``zipfile.Path``, ``SourcelessFileLoader`` audit +hooks and :func:`io.open_code`, :mod:`asyncio` UDP and introspection APIs, +``getpath.py``), and the behavior changes upstream kept to 3.13 and later +(:mod:`base64` decoding, ``Morsel.js_output``). diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 11c242a77d89677..14914a5b307722b 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.7.17.7" +#define PY_VERSION "3.7.17.8" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Include/pyexpat.h b/Include/pyexpat.h index 07020b5dc964cb3..5257bc269fa1a95 100644 --- a/Include/pyexpat.h +++ b/Include/pyexpat.h @@ -48,8 +48,13 @@ struct PyExpat_CAPI enum XML_Status (*SetEncoding)(XML_Parser parser, const XML_Char *encoding); int (*DefaultUnknownEncodingHandler)( void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); - /* might be none for expat < 2.1.0 */ + /* might be NULL for expat < 2.1.0 */ 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! */ }; diff --git a/Include/pyhash.h b/Include/pyhash.h index 9cfd071ea17ba8d..7c40f04a3c1dcab 100644 --- a/Include/pyhash.h +++ b/Include/pyhash.h @@ -38,14 +38,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. @@ -70,7 +70,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; diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 45998a13a621660..2caba925af89b47 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1501,6 +1501,17 @@ PyAPI_FUNC(PyObject*) PyUnicode_DecodeUnicodeEscape( #ifndef Py_LIMITED_API /* Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape chars. */ +PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscape2( + const char *string, /* Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + int *first_invalid_escape_char, /* on return, if not -1, contain the first + invalid escaped char in string. */ + const char **first_invalid_escape_ptr); /* on return, if not NULL, may + point to the first invalid escaped + char in string. + May be NULL if errors is not NULL. */ +// Export for binary compatibility. PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscape( const char *string, /* Unicode-Escape encoded string */ Py_ssize_t length, /* size of string */ diff --git a/Lib/configparser.py b/Lib/configparser.py index 4caf3faadc7585e..428fcbc6ea11fba 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -566,7 +566,10 @@ class RawConfigParser(MutableMapping): \] # ] """ _OPT_TMPL = r""" - (?P