diff --git a/content/posts/python-3148-31316-31215-31117-31022/index.md b/content/posts/python-3148-31316-31215-31117-31022/index.md new file mode 100644 index 0000000..810c90e --- /dev/null +++ b/content/posts/python-3148-31316-31215-31117-31022/index.md @@ -0,0 +1,93 @@ +--- +title: 'Python 3.14.8, 3.13.16, 3.12.15, 3.11.17 and 3.10.22 are now available!' +publishDate: '2026-09-30T19:00:00Z' +author: Hugo van Kemenade +description: 'Security releases for Python 3.10-3.14' +tags: + - releases +published: true +--- + +It's a big release week with Python 3.15.0 due out tomorrow, +but before that here's a full sweep of 3.10-3.14 security releases. + +* This is an expedited release for 3.14 and 3.13, which come with binary installers. + +* This is the final expected bugfix release for 3.13, which is now entering + security-fix-only mode. + +* 3.12, 3.11 and 3.10 are in security-fix-only mode with no pre-set release cadence, + and are source-only releases. + +## Security content in these releases + +* CVE-2026-19445 gh-156293 Use-after-free of a server-side `SSLContext` when `sni_callback` switches contexts + +* CVE-2026-19553 gh-156793 `SSLContext.wrap_bio()` missing validation of server_hostname parameter + +* CVE-2026-82049 gh-157190 `tarfile` extraction filters allow file modification and content disclosure via hard link to symlink + +* CVE-2026-15310 gh-156002 Memory exhaustion in `zipfile` in bzip2/LZMA/Zstandard decompression + +* CVE-2026-19672 gh-155999 `tarfile` extraction filter bypass allows creation of directories outside the destination + +* CVE-2026-15806 gh-155694 `urllib.request.HTTPPasswordMgr` credentials for one URL scheme sent over another scheme + +* CVE-2026-17084 gh-155292 `StringPrep` algorithm considered Unicode codepoint attributes outside Unicode 3.2.0 + +* gh-158446 Reject float format precision near `INT_MAX` + +* gh-157953 Update bundled Expat to [2.8.5](https://blog.hartwork.org/posts/expat-2-8-5-released/) + + +## Python 3.14.8 + +Additional fixes in this release: +* gh-158010 Update bundled OpenSSL to [3.5.9](https://openssl-library.org/news/secadv/20260929.txt) for Windows, macOS, Android and iOS + +https://www.python.org/downloads/release/python-3148/ + +## Python 3.13.16 + +Additional fixes in this release: +* CVE-2026-87910 gh-157265 `tarfile` hardlink fallback ignores custom extraction filter rejection via `None` +* gh-158010 Update bundled OpenSSL to [3.5.9](https://openssl-library.org/news/secadv/20260929.txt) for Windows, macOS and Android, a jump from 3.0.21 to the 3.5 LTS series + +https://www.python.org/downloads/release/python-31316/ + +## Python 3.12.15 + +Additional fixes in this release: +* CVE-2026-87910 gh-157265 `tarfile` hardlink fallback ignores custom extraction filter rejection via `None` + +https://www.python.org/downloads/release/python-31215/ + +## Python 3.11.17 + +Additional fixes in this release: +* CVE-2026-87910 gh-157265 `tarfile` hardlink fallback ignores custom extraction filter rejection via `None` + +https://www.python.org/downloads/release/python-31117/ + +## Python 3.10.22 + +Additional fixes in this release: +* CVE-2026-87910 gh-157265 `tarfile` hardlink fallback ignores custom extraction filter rejection via `None` + +https://www.python.org/downloads/release/python-31022/ + +## Stay safe and upgrade! + +As always, upgrading is highly recommended to all users of affected versions. + +## Enjoy the new releases + +Thanks to all of the many volunteers who help make Python development and these +releases possible! Please consider supporting our efforts by volunteering yourself +or through organisation contributions to the [Python Software Foundation](https://www.python.org/psf-landing/). + +Your release team, +Hugo van Kemenade +Thomas Wouters +Pablo Galindo Salgado +Ned Deily diff --git a/src/layouts/BlogPostLayout.astro b/src/layouts/BlogPostLayout.astro index a6ed15c..b5d2272 100644 --- a/src/layouts/BlogPostLayout.astro +++ b/src/layouts/BlogPostLayout.astro @@ -37,6 +37,7 @@ const groupMeta: Record = { "gh-repo": { label: "Repositories", order: 2 }, "gh-user": { label: "People", order: 3 }, "pypi": { label: "Packages", order: 4 }, + "cve": { label: "Security", order: 5 }, }; const sortedGroups = [...refGroups.entries()] @@ -195,6 +196,7 @@ const sortedGroups = [...refGroups.entries()] type === "gh-repo" && "bg-zinc-100 text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700", type === "gh-user" && "bg-zinc-100 text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700", type === "pypi" && "bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:bg-emerald-900/20 dark:text-emerald-300 dark:hover:bg-emerald-900/40", + type === "cve" && "bg-rose-50 text-rose-700 hover:bg-rose-100 dark:bg-rose-900/20 dark:text-rose-300 dark:hover:bg-rose-900/40", ]} target="_blank" rel="noopener noreferrer" diff --git a/src/plugins/remark-python-refs.ts b/src/plugins/remark-python-refs.ts index de7713a..04351e7 100644 --- a/src/plugins/remark-python-refs.ts +++ b/src/plugins/remark-python-refs.ts @@ -13,9 +13,12 @@ * - GitHub users/orgs (github.com/NAME — exactly 1 segment, not reserved) * - CVE references (nvd.nist.gov/vuln/detail/CVE-YYYY-NNNNN) * - Python releases (python.org/downloads/release/python-XXXX/) + * + * Bare "gh-NNNN" and "CVE-YYYY-NNNN" text (not already inside a link + * or heading) is autolinked and rendered as a badge. */ import type { Root, Link, Paragraph, PhrasingContent } from "mdast"; -import { visit } from "unist-util-visit"; +import { SKIP, visit } from "unist-util-visit"; import { pythonIcon, docsIcon, @@ -35,6 +38,14 @@ const DOCS = /^https?:\/\/docs\.python\.org\//i; const PYPI = /^https?:\/\/pypi\.org\/project\/([^/]+)\/?/i; const GH_ISSUE = /^https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/(issues|pull)\/(\d+)\/?/i; const CVE = /^https?:\/\/nvd\.nist\.gov\/vuln\/detail\/(CVE-[\d-]+)\/?/i; + +/** + * Bare references in plain text that get autolinked (outside links, + * headings and code): + * - "gh-156293" → python/cpython issue + * - "CVE-2026-19445" → cve.org record + */ +const BARE_REF = /\b(?:(CVE-\d{4}-\d{4,})|gh-(\d+))\b/g; const PY_RELEASE = /^https?:\/\/(?:www\.)?python\.org\/downloads\/release\/(python-[\w.]+)\/?/i; const GITHUB = /^https?:\/\/github\.com\/([\w.-]+)(?:\/([\w.-]+))?\/?$/i; @@ -330,6 +341,48 @@ export default function remarkPythonRefs() { } }); + // Pass 3: Autolink bare gh-NNNN issue refs and CVE IDs in text → badges + visit(tree, (node: any, index, parent: any) => { + // Don't touch text that is already a link (or a reference definition), + // or headings — Astro builds heading ids from text nodes only, so + // injecting HTML there would change the anchor slug. + if ( + node.type === "link" || + node.type === "linkReference" || + node.type === "definition" || + node.type === "heading" + ) { + return SKIP; + } + if (node.type !== "text" || index == null || !parent) return; + + const value: string = node.value; + const parts: any[] = []; + let lastIndex = 0; + BARE_REF.lastIndex = 0; + let m: RegExpExecArray | null; + while ((m = BARE_REF.exec(value)) !== null) { + if (m.index > lastIndex) { + parts.push({ type: "text", value: value.slice(lastIndex, m.index) }); + } + const [label, cve, ghNum] = m; + const match: Match = cve + ? { type: "cve", icon: shieldIcon, label, url: `https://www.cve.org/CVERecord?id=${cve}` } + : { type: "gh-issue", icon: issueIcon, label, url: `https://github.com/python/cpython/issues/${ghNum}` }; + collectRef(match.type, match.label, match.url); + parts.push({ type: "html", value: buildBadgeHtml(match) }); + lastIndex = m.index + m[0].length; + } + if (parts.length === 0) return; + if (lastIndex < value.length) { + parts.push({ type: "text", value: value.slice(lastIndex) }); + } + + parent.children.splice(index, 1, ...parts); + // Continue after the nodes we just inserted + return index + parts.length; + }); + // Expose collected references via remarkPluginFrontmatter if (!file.data.astro) file.data.astro = {}; if (!file.data.astro.frontmatter) file.data.astro.frontmatter = {};