diff --git a/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273-pre1.patch b/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273-pre1.patch new file mode 100644 index 0000000000..d75f05fc68 --- /dev/null +++ b/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273-pre1.patch @@ -0,0 +1,55 @@ +From d8390feaa99091d1ba9626bec0e4ba7072fc507a Mon Sep 17 00:00:00 2001 +From: "Jason R. Coombs" +Date: Sat, 19 Apr 2025 12:49:55 -0400 +Subject: [PATCH] Extract _resolve_download_filename with test. + +CVE: CVE-2025-47273 #Dependency Patch + +Upstream-Status: Backport [https://github.com/pypa/setuptools/commit/d8390feaa99091d1ba9626bec0e4ba7072fc507a] + +Signed-off-by: Praveen Kumar +--- + setuptools/package_index.py | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/setuptools/package_index.py b/setuptools/package_index.py +index 1a6abeb..b317735 100644 +--- a/setuptools/package_index.py ++++ b/setuptools/package_index.py +@@ -807,9 +807,16 @@ class PackageIndex(Environment): + else: + raise DistutilsError(f"Download error for {url}: {v}") from v + +- def _download_url(self, url, tmpdir): +- # Determine download filename +- # ++ @staticmethod ++ def _resolve_download_filename(url, tmpdir): ++ """ ++ >>> 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' ++ """ + name, _fragment = egg_info_for_url(url) + if name: + while '..' in name: +@@ -820,8 +827,13 @@ class PackageIndex(Environment): + if name.endswith('.egg.zip'): + name = name[:-4] # strip the extra .zip before download + +- filename = os.path.join(tmpdir, name) ++ return os.path.join(tmpdir, name) + ++ def _download_url(self, url, tmpdir): ++ """ ++ Determine the download filename. ++ """ ++ filename = self._resolve_download_filename(url, tmpdir) + return self._download_vcs(url, filename) or self._download_other(url, filename) + + @staticmethod +-- +2.40.0 diff --git a/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273.patch b/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273.patch new file mode 100644 index 0000000000..3c44a2a321 --- /dev/null +++ b/meta/recipes-devtools/python/python3-setuptools/CVE-2025-47273.patch @@ -0,0 +1,60 @@ +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 + +CVE: CVE-2025-47273 + +Upstream-Status: Backport [https://github.com/pypa/setuptools/commit/250a6d17978f9f6ac3ac887091f2d32886fbbb0b] + +Signed-off-by: Praveen Kumar +--- + 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 b317735..a8f868e 100644 +--- a/setuptools/package_index.py ++++ b/setuptools/package_index.py +@@ -810,12 +810,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: +@@ -827,7 +835,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.40.0 diff --git a/meta/recipes-devtools/python/python3-setuptools_76.0.0.bb b/meta/recipes-devtools/python/python3-setuptools_76.0.0.bb index 71c8eb1a1f..91d8fdd73b 100644 --- a/meta/recipes-devtools/python/python3-setuptools_76.0.0.bb +++ b/meta/recipes-devtools/python/python3-setuptools_76.0.0.bb @@ -11,7 +11,10 @@ CVE_PRODUCT = "python3-setuptools python:setuptools" SRC_URI:append:class-native = " file://0001-conditionally-do-not-fetch-code-by-easy_install.patch" SRC_URI += " \ - file://0001-_distutils-sysconfig.py-make-it-possible-to-substite.patch" + file://0001-_distutils-sysconfig.py-make-it-possible-to-substite.patch \ + file://CVE-2025-47273-pre1.patch \ + file://CVE-2025-47273.patch \ +" SRC_URI[sha256sum] = "43b4ee60e10b0d0ee98ad11918e114c70701bc6051662a9a675a0496c1a158f4"