From 45599cca46672873080d553428c6d0eafa5fe752 Mon Sep 17 00:00:00 2001 From: Dylan Eustice Date: Fri, 19 Dec 2025 08:19:58 -0500 Subject: [PATCH 1/3] Quote packages in pip install to avoid shell expansion Without quotes, pip installs with versioning that includes characters '<', '>', or '|' result in shell expansion and creation of unwanted files Signed-off-by: Dylan Eustice --- hpccm/building_blocks/pip.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hpccm/building_blocks/pip.py b/hpccm/building_blocks/pip.py index b1ba4a0d..499ed5f3 100644 --- a/hpccm/building_blocks/pip.py +++ b/hpccm/building_blocks/pip.py @@ -165,6 +165,8 @@ def __instructions(self): posixpath.basename(self.__requirements))])) if self.__packages: + # Quote the packages to avoid shell expansion + quoted_packages = [f'"{pkg}"' for pkg in self.__packages] cmds.append('{0} install {1}'.format(self.__pip, - ' '.join(self.__packages))) + ' '.join(quoted_packages))) self += shell(commands=cmds) From 6a9ef445d4ab6f39dcd57147036f822acadfe09c Mon Sep 17 00:00:00 2001 From: Dylan Eustice Date: Fri, 19 Dec 2025 08:23:40 -0500 Subject: [PATCH 2/3] Update unit tests to expect quotes --- test/test_pip.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test_pip.py b/test/test_pip.py index 980e2106..6458f16f 100644 --- a/test/test_pip.py +++ b/test/test_pip.py @@ -44,7 +44,7 @@ def test_defaults_ubuntu(self): python-setuptools \ python-wheel && \ rm -rf /var/lib/apt/lists/* -RUN pip --no-cache-dir install hpccm''') +RUN pip --no-cache-dir install "hpccm"''') @centos @docker @@ -57,7 +57,7 @@ def test_defaults_centos(self): yum install -y \ python2-pip && \ rm -rf /var/cache/yum/* -RUN pip --no-cache-dir install hpccm''') +RUN pip --no-cache-dir install "hpccm"''') @centos8 @docker @@ -71,7 +71,7 @@ def test_alternatives_centos8(self): rm -rf /var/cache/yum/* RUN alternatives --set python /usr/bin/python2 && \ alternatives --install /usr/bin/pip pip /usr/bin/pip2 30 -RUN pip --no-cache-dir install hpccm''') +RUN pip --no-cache-dir install "hpccm"''') @ubuntu @docker @@ -86,7 +86,7 @@ def test_pip3_ubuntu(self): python3-setuptools \ python3-wheel && \ rm -rf /var/lib/apt/lists/* -RUN pip3 --no-cache-dir install hpccm''') +RUN pip3 --no-cache-dir install "hpccm"''') @centos @docker @@ -98,7 +98,7 @@ def test_pip3_centos(self): RUN yum install -y \ python3-pip && \ rm -rf /var/cache/yum/* -RUN pip3 --no-cache-dir install hpccm''') +RUN pip3 --no-cache-dir install "hpccm"''') @centos @docker @@ -110,7 +110,7 @@ def test_no_args(self): RUN yum install -y \ python3-pip && \ rm -rf /var/cache/yum/* -RUN pip3 install hpccm''') +RUN pip3 install "hpccm"''') @ubuntu @docker @@ -119,7 +119,7 @@ def test_no_ospackages(self): p = pip(ospackages=[], packages=['hpccm']) self.assertEqual(str(p), r'''# pip -RUN pip --no-cache-dir install hpccm''') +RUN pip --no-cache-dir install "hpccm"''') @ubuntu @docker @@ -132,7 +132,7 @@ def test_ospackages(self): DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ foo && \ rm -rf /var/lib/apt/lists/* -RUN pip --no-cache-dir install hpccm''') +RUN pip --no-cache-dir install "hpccm"''') @ubuntu @docker @@ -165,4 +165,4 @@ def test_upgrade(self): python-wheel && \ rm -rf /var/lib/apt/lists/* RUN pip --no-cache-dir install --upgrade "pip < 21.0" && \ - pip --no-cache-dir install hpccm''') + pip --no-cache-dir install "hpccm"''') From ff40172666460988c85891ee3f15e2f5fa50a9a5 Mon Sep 17 00:00:00 2001 From: Dylan Eustice Date: Fri, 19 Dec 2025 11:19:26 -0500 Subject: [PATCH 3/3] Use shlex_quotes from six.moves instead of f-string and update unit tests Signed-off-by: Dylan Eustice --- hpccm/building_blocks/pip.py | 3 ++- test/test_pip.py | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/hpccm/building_blocks/pip.py b/hpccm/building_blocks/pip.py index 499ed5f3..178b46c6 100644 --- a/hpccm/building_blocks/pip.py +++ b/hpccm/building_blocks/pip.py @@ -24,6 +24,7 @@ from packaging.version import Version import logging import posixpath +from six.moves import shlex_quote import hpccm.config import hpccm.templates.rm @@ -166,7 +167,7 @@ def __instructions(self): if self.__packages: # Quote the packages to avoid shell expansion - quoted_packages = [f'"{pkg}"' for pkg in self.__packages] + quoted_packages = [shlex_quote(pkg) for pkg in self.__packages] cmds.append('{0} install {1}'.format(self.__pip, ' '.join(quoted_packages))) self += shell(commands=cmds) diff --git a/test/test_pip.py b/test/test_pip.py index 6458f16f..1bc64985 100644 --- a/test/test_pip.py +++ b/test/test_pip.py @@ -44,7 +44,7 @@ def test_defaults_ubuntu(self): python-setuptools \ python-wheel && \ rm -rf /var/lib/apt/lists/* -RUN pip --no-cache-dir install "hpccm"''') +RUN pip --no-cache-dir install hpccm''') @centos @docker @@ -57,7 +57,7 @@ def test_defaults_centos(self): yum install -y \ python2-pip && \ rm -rf /var/cache/yum/* -RUN pip --no-cache-dir install "hpccm"''') +RUN pip --no-cache-dir install hpccm''') @centos8 @docker @@ -71,7 +71,7 @@ def test_alternatives_centos8(self): rm -rf /var/cache/yum/* RUN alternatives --set python /usr/bin/python2 && \ alternatives --install /usr/bin/pip pip /usr/bin/pip2 30 -RUN pip --no-cache-dir install "hpccm"''') +RUN pip --no-cache-dir install hpccm''') @ubuntu @docker @@ -86,7 +86,7 @@ def test_pip3_ubuntu(self): python3-setuptools \ python3-wheel && \ rm -rf /var/lib/apt/lists/* -RUN pip3 --no-cache-dir install "hpccm"''') +RUN pip3 --no-cache-dir install hpccm''') @centos @docker @@ -98,7 +98,7 @@ def test_pip3_centos(self): RUN yum install -y \ python3-pip && \ rm -rf /var/cache/yum/* -RUN pip3 --no-cache-dir install "hpccm"''') +RUN pip3 --no-cache-dir install hpccm''') @centos @docker @@ -110,7 +110,7 @@ def test_no_args(self): RUN yum install -y \ python3-pip && \ rm -rf /var/cache/yum/* -RUN pip3 install "hpccm"''') +RUN pip3 install hpccm''') @ubuntu @docker @@ -119,7 +119,7 @@ def test_no_ospackages(self): p = pip(ospackages=[], packages=['hpccm']) self.assertEqual(str(p), r'''# pip -RUN pip --no-cache-dir install "hpccm"''') +RUN pip --no-cache-dir install hpccm''') @ubuntu @docker @@ -132,7 +132,7 @@ def test_ospackages(self): DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ foo && \ rm -rf /var/lib/apt/lists/* -RUN pip --no-cache-dir install "hpccm"''') +RUN pip --no-cache-dir install hpccm''') @ubuntu @docker @@ -165,4 +165,13 @@ def test_upgrade(self): python-wheel && \ rm -rf /var/lib/apt/lists/* RUN pip --no-cache-dir install --upgrade "pip < 21.0" && \ - pip --no-cache-dir install "hpccm"''') + pip --no-cache-dir install hpccm''') + + @ubuntu + @docker + def test_package_with_version(self): + """package with version specifier is quoted""" + p = pip(ospackages=[], packages=['hpccm>=1.0']) + self.assertEqual(str(p), +r"""# pip +RUN pip --no-cache-dir install 'hpccm>=1.0'""")