new file mode 100644
@@ -0,0 +1,98 @@
+From 19b8b2011fd1743841510e44b8e9e87f3a3f4ba0 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <encukou@gmail.com>
+Date: Fri, 11 Sep 2026 14:19:35 +0200
+Subject: [PATCH] gh-157265: tarfile: Honor None result of filter for link
+ fallbacks (GH-157266)
+
+Co-authored-by: Stan Ulbrych <stan@python.org>
+
+CVE: CVE-2026-87910
+Upstream-Status: Backport [https://github.com/python/cpython/commit/fb2f0bbc3b35264f09cc2cb2934b7987527a6bc2]
+
+(cherry picked from commit fb2f0bbc3b35264f09cc2cb2934b7987527a6bc2)
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ Lib/tarfile.py | 4 ++-
+ Lib/test/test_tarfile.py | 31 +++++++++++++++++--
+ ...-09-10-13-38-11.gh-issue-157265.-vYuMp.rst | 3 ++
+ 3 files changed, 34 insertions(+), 4 deletions(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2026-09-10-13-38-11.gh-issue-157265.-vYuMp.rst
+
+diff --git a/Lib/tarfile.py b/Lib/tarfile.py
+index b7b4af15b1..89e1e9b218 100644
+--- a/Lib/tarfile.py
++++ b/Lib/tarfile.py
+@@ -2818,9 +2818,11 @@ class TarFile(object):
+ "makelink_with_filter: if filter_function is not None, "
+ + "extraction_root must also not be None")
+ try:
+- filter_function(
++ filtered = filter_function(
+ unfiltered.replace(name=tarinfo.name, deep=False),
+ extraction_root)
++ if filtered is None:
++ return
+ filtered = filter_function(unfiltered, extraction_root)
+ except _FILTER_ERRORS as cause:
+ raise LinkFallbackError(tarinfo, unfiltered.name) from cause
+diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
+index ab13ab34fc..c09592075b 100644
+--- a/Lib/test/test_tarfile.py
++++ b/Lib/test/test_tarfile.py
+@@ -4395,9 +4395,15 @@ class TestExtractionFilters(unittest.TestCase):
+ for filter in 'tar', 'fully_trusted':
+ with self.subTest(filter), self.check_context(arc.open(), filter):
+ if not os_helper.can_symlink():
+- self.expect_file("a/t/dummy")
+- self.expect_file("b/")
+- self.expect_file("c/")
++ if filter == 'tar':
++ self.expect_exception(
++ tarfile.LinkFallbackError,
++ "link 'boom' would be extracted as a copy of "
++ + "'c/escape', which was rejected")
++ else:
++ self.expect_file("a/t/dummy")
++ self.expect_file("b/")
++ self.expect_file("c/")
+ else:
+ self.expect_file("a/t/dummy")
+ self.expect_file("b/")
+@@ -4576,6 +4582,25 @@ class TestExtractionFilters(unittest.TestCase):
+ if os_helper.can_chmod():
+ self.assertFalse(path.stat().st_mode & stat.S_IWUSR)
+
++ @symlink_test
++ def test_extract_filters_target_none(self):
++ # Test that when extract() falls back to extracting (rather than
++ # linking) a hardlink target, the member is skipped if the filter
++ # returns None.
++ with ArchiveMaker() as arc:
++ arc.add('a/b/s', symlink_to='../escape')
++ arc.add('q', hardlink_to='a/b/s')
++ def filter_unsafe_members(member, path):
++ try:
++ return tarfile.data_filter(member, path)
++ except tarfile.FilterError as error:
++ return None
++ with self.check_context(arc.open(), filter_unsafe_members):
++ if os_helper.can_symlink():
++ self.expect_file('a/b/s', symlink_to='../escape')
++ else:
++ self.expect_file('a/b/') # symlink is not extracted
++
+ def test_link_fallback_normalizes(self):
+ # Make sure hardlink fallbacks work for non-normalized paths for all
+ # filters
+diff --git a/Misc/NEWS.d/next/Security/2026-09-10-13-38-11.gh-issue-157265.-vYuMp.rst b/Misc/NEWS.d/next/Security/2026-09-10-13-38-11.gh-issue-157265.-vYuMp.rst
+new file mode 100644
+index 0000000000..ba27e47f73
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2026-09-10-13-38-11.gh-issue-157265.-vYuMp.rst
+@@ -0,0 +1,3 @@
++In :mod:`tarfile`, when extracting a link falls back to extracting a member
++of the archive, skip the member when the filter function returns None when
++called with the extracted member's name replaced with the link's.
+--
+2.35.6
+
new file mode 100644
@@ -0,0 +1,55 @@
+From 8dd3fcd26e7effd2de3b3ec7709d80632b6acfc7 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <encukou@gmail.com>
+Date: Fri, 11 Sep 2026 19:54:41 +0200
+Subject: [PATCH] gh-157265: Adjust test for Windows (GH-157334)
+
+gh-157266: Adjust test for Windows
+
+On Windows (no symlinks, no hardlinks), the behaviour is
+the same as without the fix in GH-157266:
+- a/t/dummy is extracted
+- b/ is extracted
+- c/ is *not* created (the target, a/t, is not in the archive)
+- c/escape: c/ is created; escape is skipped (target,
+ c/../../link_here, is not in archive)
+- c is not recreated as a directory
+- boom is not created (target is c/escape, which falls back to
+ ..\..\link_here, which does not exist in archive)
+
+CVE: CVE-2026-87910
+Upstream-Status: Backport [https://github.com/python/cpython/commit/d9565e54b1fc6d63c5be9afd58114499128fa57b]
+
+(cherry picked from commit d9565e54b1fc6d63c5be9afd58114499128fa57b)
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ Lib/test/test_tarfile.py | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
+index c09592075b..7e072d9090 100644
+--- a/Lib/test/test_tarfile.py
++++ b/Lib/test/test_tarfile.py
+@@ -4395,15 +4395,15 @@ class TestExtractionFilters(unittest.TestCase):
+ for filter in 'tar', 'fully_trusted':
+ with self.subTest(filter), self.check_context(arc.open(), filter):
+ if not os_helper.can_symlink():
+- if filter == 'tar':
++ if filter == 'fully_trusted' or sys.platform == "win32":
++ self.expect_file("a/t/dummy")
++ self.expect_file("b/")
++ self.expect_file("c/")
++ else:
+ self.expect_exception(
+ tarfile.LinkFallbackError,
+ "link 'boom' would be extracted as a copy of "
+ + "'c/escape', which was rejected")
+- else:
+- self.expect_file("a/t/dummy")
+- self.expect_file("b/")
+- self.expect_file("c/")
+ else:
+ self.expect_file("a/t/dummy")
+ self.expect_file("b/")
+--
+2.35.6
+
@@ -36,6 +36,8 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
file://0001-test_only_active_thread-skip-problematic-test.patch \
file://0001-prefer-valid-entrypoints.patch \
file://CVE-2025-15367.patch \
+ file://CVE-2026-87910_p1.patch \
+ file://CVE-2026-87910_p2.patch \
"
SRC_URI:append:class-native = " \
file://0001-Lib-sysconfig.py-use-prefix-value-from-build-configu.patch \