From 064c5a14690725a71565da63ccb688c0a63a6f57 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 24 Jul 2024 14:15:57 +0200 Subject: [PATCH] CVE-2024-6345 --- setuptools/package_index.py | 29 +++++++++------------------ setuptools/tests/test_packageindex.py | 28 +++++++++++++------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 362e26f..dfc591b 100644 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -1,5 +1,6 @@ """PyPI and direct package downloading.""" +import subprocess import sys import os import re @@ -874,7 +875,7 @@ class PackageIndex(Environment): def _download_svn(self, url, filename): warnings.warn("SVN download support is deprecated", UserWarning) url = url.split('#', 1)[0] # remove any fragment for svn's sake - creds = '' + creds = [] if url.lower().startswith('svn:') and '@' in url: scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) if not netloc and path.startswith('//') and '/' in path[2:]: @@ -883,14 +884,14 @@ class PackageIndex(Environment): if auth: if ':' in auth: user, pw = auth.split(':', 1) - creds = " --username=%s --password=%s" % (user, pw) + creds = [f"--username={user}", f"--password={pw}"] else: - creds = " --username=" + auth + creds = [f"--username={auth}"] netloc = host parts = scheme, netloc, url, p, q, f url = urllib.parse.urlunparse(parts) self.info("Doing subversion checkout from %s to %s", url, filename) - os.system("svn checkout%s -q %s %s" % (creds, url, filename)) + subprocess.check_call(["svn", "checkout"] + creds + ["-q", url, filename]) return filename @staticmethod @@ -916,17 +917,11 @@ class PackageIndex(Environment): url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) self.info("Doing git clone from %s to %s", url, filename) - os.system("git clone --quiet %s %s" % (url, filename)) + subprocess.check_call(["git", "clone", "--quiet", url, filename]) if rev is not None: self.info("Checking out %s", rev) - os.system( - "git -C %s checkout --quiet %s" - % ( - filename, - rev, - ) - ) + subprocess.check_call(["git", "-C", filename, "checkout", "--quiet", rev]) return filename @@ -935,17 +930,11 @@ class PackageIndex(Environment): url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) self.info("Doing hg clone from %s to %s", url, filename) - os.system("hg clone --quiet %s %s" % (url, filename)) + subprocess.check_call(["hg", "clone", "--quiet", url, filename]) if rev is not None: self.info("Updating to %s", rev) - os.system( - "hg --cwd %s up -C -r %s -q" - % ( - filename, - rev, - ) - ) + subprocess.check_call(["hg", "--cwd", filename, "up", "-C", "-r", rev, "-q"]) return filename diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 7b0bf11..cf24def 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -190,53 +190,53 @@ class TestPackageIndex: url = 'git+https://github.example/group/project@master#egg=foo' index = setuptools.package_index.PackageIndex() - with mock.patch("os.system") as os_system_mock: + with mock.patch("subprocess.check_call") as subprocess_check_call_mock: result = index.download(url, str(tmpdir)) - os_system_mock.assert_called() + subprocess_check_call_mock.assert_called() expected_dir = str(tmpdir / 'project@master') expected = ( 'git clone --quiet ' 'https://github.example/group/project {expected_dir}' - ).format(**locals()) - first_call_args = os_system_mock.call_args_list[0][0] + ).format(**locals()).split() + first_call_args = subprocess_check_call_mock.call_args_list[0][0] assert first_call_args == (expected,) tmpl = 'git -C {expected_dir} checkout --quiet master' - expected = tmpl.format(**locals()) - assert os_system_mock.call_args_list[1][0] == (expected,) + expected = tmpl.format(**locals()).split() + assert subprocess_check_call_mock.call_args_list[1][0] == (expected,) assert result == expected_dir def test_download_git_no_rev(self, tmpdir): url = 'git+https://github.example/group/project#egg=foo' index = setuptools.package_index.PackageIndex() - with mock.patch("os.system") as os_system_mock: + with mock.patch("subprocess.check_call") as subprocess_check_call_mock: result = index.download(url, str(tmpdir)) - os_system_mock.assert_called() + subprocess_check_call_mock.assert_called() expected_dir = str(tmpdir / 'project') expected = ( 'git clone --quiet ' 'https://github.example/group/project {expected_dir}' - ).format(**locals()) - os_system_mock.assert_called_once_with(expected) + ).format(**locals()).split() + subprocess_check_call_mock.assert_called_once_with(expected) def test_download_svn(self, tmpdir): url = 'svn+https://svn.example/project#egg=foo' index = setuptools.package_index.PackageIndex() with pytest.warns(UserWarning): - with mock.patch("os.system") as os_system_mock: + with mock.patch("subprocess.check_call") as subprocess_check_call_mock: result = index.download(url, str(tmpdir)) - os_system_mock.assert_called() + subprocess_check_call_mock.assert_called() expected_dir = str(tmpdir / 'project') expected = ( 'svn checkout -q ' 'svn+https://svn.example/project {expected_dir}' - ).format(**locals()) - os_system_mock.assert_called_once_with(expected) + ).format(**locals()).split() + subprocess_check_call_mock.assert_called_once_with(expected) class TestContentCheckers: -- 2.45.2