Skip to content

Commit 358ccda

Browse files
committed
feat(Makefile): set default goal to 'all' for easier command execution
feat(shell_executor.py): add _create_shell_command method to safely create shell command strings and prevent shell injection refactor(shell_executor.py): change subprocess execution to use create_subprocess_shell for improved command handling
1 parent da8c856 commit 358ccda

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.PHONY: test format lint typecheck check
2+
.DEFAULT_GOAL := all
23

34
test:
45
pip install -e .
@@ -21,4 +22,4 @@ typecheck:
2122
# Run all checks required before pushing
2223
check: lint typecheck test
2324
fix: check format
24-
all: check
25+
all: check test

src/mcp_shell_server/shell_executor.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import os
3+
import shlex
34
import time
45
from typing import Any, Dict, List, Optional
56

@@ -40,6 +41,19 @@ def _clean_command(self, command: List[str]) -> List[str]:
4041
"""
4142
return [arg.strip() for arg in command if arg.strip()]
4243

44+
def _create_shell_command(self, command: List[str]) -> str:
45+
"""
46+
Create a shell command string from a list of arguments.
47+
Properly escapes all arguments to prevent shell injection.
48+
49+
Args:
50+
command (List[str]): Command and its arguments
51+
52+
Returns:
53+
str: Shell-safe command string
54+
"""
55+
return " ".join(shlex.quote(arg) for arg in command)
56+
4357
def _validate_command(self, command: List[str]) -> None:
4458
"""
4559
Validate if the command is allowed to be executed.
@@ -140,9 +154,10 @@ async def execute(
140154
}
141155

142156
try:
143-
process = await asyncio.create_subprocess_exec(
144-
cleaned_command[0],
145-
*cleaned_command[1:],
157+
# Create shell command and execute it
158+
shell_command = self._create_shell_command(cleaned_command)
159+
process = await asyncio.create_subprocess_shell(
160+
shell_command,
146161
stdin=asyncio.subprocess.PIPE if stdin else None,
147162
stdout=asyncio.subprocess.PIPE,
148163
stderr=asyncio.subprocess.PIPE,

0 commit comments

Comments
 (0)