From 250a6d17978f9f6ac3ac887091f2d32886fbbb0b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" 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 --- 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 d460fcb..6c7874d 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -818,12 +818,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: @@ -835,7 +843,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