From 250a6d17978f9f6ac3ac887091f2d32886fbbb0b Mon Sep 17 00:00:00 2001
From: "Jason R. Coombs" <jaraco@jaraco.com>
Date: Sat, 19 Apr 2025 13:03:47 -0400
Subject: [PATCH] Add a check to ensure the name resolves relative to the
 tmpdir.

Closes #4946

Upstream-Status: Backport [https://github.com/pypa/setuptools/commit/250a6d17978f9f6ac3ac887091f2d32886fbbb0b]
CVE: CVE-2025-47273
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
---
 setuptools/package_index.py | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index f350e11..86bf851 100644
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -789,12 +789,20 @@ class PackageIndex(Environment):
     @staticmethod
     def _resolve_download_filename(url, tmpdir):
         """
+        >>> import pathlib
         >>> du = PackageIndex._resolve_download_filename
         >>> root = getfixture('tmp_path')
         >>> url = 'https://files.pythonhosted.org/packages/a9/5a/0db.../setuptools-78.1.0.tar.gz'
-        >>> import pathlib
         >>> str(pathlib.Path(du(url, root)).relative_to(root))
         'setuptools-78.1.0.tar.gz'
+
+        Ensures the target is always in tmpdir.
+
+        >>> url = 'https://anyhost/%2fhome%2fuser%2f.ssh%2fauthorized_keys'
+        >>> du(url, root)
+        Traceback (most recent call last):
+        ...
+        ValueError: Invalid filename...
         """
         name, fragment = egg_info_for_url(url)
         if name:
@@ -806,7 +814,13 @@ class PackageIndex(Environment):
         if name.endswith('.egg.zip'):
             name = name[:-4]  # strip the extra .zip before download
 
-        return os.path.join(tmpdir, name)
+        filename = os.path.join(tmpdir, name)
+
+        # ensure path resolves within the tmpdir
+        if not filename.startswith(str(tmpdir)):
+            raise ValueError(f"Invalid filename {filename}")
+
+        return filename
 
     def _download_url(self, url, tmpdir):
         """
-- 
2.25.1

