diff --git a/src/openllm/common.py b/src/openllm/common.py index c3646ba69..f17103f6b 100644 --- a/src/openllm/common.py +++ b/src/openllm/common.py @@ -422,12 +422,8 @@ async def async_run_command( proc = None try: - proc = await asyncio.create_subprocess_shell( - ' '.join(map(str, cmd)), - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - cwd=cwd, - env=env, + proc = await asyncio.create_subprocess_exec( + *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=cwd, env=env ) yield proc except subprocess.CalledProcessError: @@ -435,7 +431,8 @@ async def async_run_command( raise typer.Exit(1) finally: if proc: - proc.send_signal(signal.SIGINT) + if proc.returncode is None: + proc.send_signal(signal.SIGINT) await proc.wait() diff --git a/tests/test_common.py b/tests/test_common.py new file mode 100644 index 000000000..a9388523e --- /dev/null +++ b/tests/test_common.py @@ -0,0 +1,23 @@ +import asyncio +import os + +from openllm.common import async_run_command + + +def test_async_run_command_does_not_invoke_shell(tmp_path): + marker = tmp_path / 'shell_injection_marker.txt' + if os.name == 'nt': + separator = '&' + payload = ['cmd', '/c', f'echo PWNED>{marker}'] + else: + separator = ';' + payload = ['sh', '-c', f'echo PWNED > {marker}'] + + async def run() -> None: + cmd = ['python', '-c', 'pass', separator, *payload] + async with async_run_command(cmd, cwd=str(tmp_path), silent=True) as proc: + await proc.wait() + + asyncio.run(run()) + + assert not marker.exists()