diff --git a/tools/environments/docker.py b/tools/environments/docker.py index ea553a7b60d..b10520667a0 100644 --- a/tools/environments/docker.py +++ b/tools/environments/docker.py @@ -8,6 +8,7 @@ persistence via bind mounts. import logging import os import re +import shlex import shutil import subprocess import sys @@ -486,7 +487,7 @@ class DockerEnvironment(BaseEnvironment): # docker exec -w doesn't expand ~, so prepend a cd into the command if work_dir == "~" or work_dir.startswith("~/"): - exec_command = f"cd {work_dir} && {exec_command}" + exec_command = f"cd {shlex.quote(work_dir)} && {exec_command}" work_dir = "/" assert self._container_id, "Container not started" diff --git a/tools/environments/singularity.py b/tools/environments/singularity.py index 89d9ffb04b4..c82c53d71be 100644 --- a/tools/environments/singularity.py +++ b/tools/environments/singularity.py @@ -8,6 +8,7 @@ via writable overlay directories that survive across sessions. import json import logging import os +import shlex import shutil import subprocess import tempfile @@ -313,7 +314,7 @@ class SingularityEnvironment(BaseEnvironment): # apptainer exec --pwd doesn't expand ~, so prepend a cd into the command if work_dir == "~" or work_dir.startswith("~/"): - exec_command = f"cd {work_dir} && {exec_command}" + exec_command = f"cd {shlex.quote(work_dir)} && {exec_command}" work_dir = "/tmp" cmd = [self.executable, "exec", "--pwd", work_dir, diff --git a/tools/environments/ssh.py b/tools/environments/ssh.py index 387dea34e0f..f77e3faac9b 100644 --- a/tools/environments/ssh.py +++ b/tools/environments/ssh.py @@ -1,6 +1,7 @@ """SSH remote execution environment with ControlMaster connection persistence.""" import logging +import shlex import shutil import subprocess import tempfile @@ -228,7 +229,7 @@ class SSHEnvironment(PersistentShellMixin, BaseEnvironment): stdin_data: str | None = None) -> dict: work_dir = cwd or self.cwd exec_command, sudo_stdin = self._prepare_command(command) - wrapped = f'cd {work_dir} && {exec_command}' + wrapped = f'cd {shlex.quote(work_dir)} && {exec_command}' effective_timeout = timeout or self.timeout if sudo_stdin is not None and stdin_data is not None: