mirror of
https://github.com/trycua/computer.git
synced 2026-01-01 19:10:30 -06:00
Merge pull request #519 from AdityaBavadekar/sanitize-shell-input
This commit is contained in:
@@ -10,6 +10,8 @@ import subprocess
|
||||
import urllib.parse
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from computer.utils import safe_join
|
||||
|
||||
# Setup logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -59,7 +61,7 @@ def lume_api_get(
|
||||
# --max-time: Maximum time for the whole operation (20 seconds)
|
||||
# -f: Fail silently (no output at all) on server errors
|
||||
# Add single quotes around URL to ensure special characters are handled correctly
|
||||
cmd = ["curl", "--connect-timeout", "15", "--max-time", "20", "-s", "-f", f"'{api_url}'"]
|
||||
cmd = ["curl", "--connect-timeout", "15", "--max-time", "20", "-s", "-f", api_url]
|
||||
|
||||
# For logging and display, show the properly escaped URL
|
||||
display_cmd = ["curl", "--connect-timeout", "15", "--max-time", "20", "-s", "-f", api_url]
|
||||
@@ -71,7 +73,7 @@ def lume_api_get(
|
||||
# Execute the command - for execution we need to use shell=True to handle URLs with special characters
|
||||
try:
|
||||
# Use a single string with shell=True for proper URL handling
|
||||
shell_cmd = " ".join(cmd)
|
||||
shell_cmd = safe_join(cmd)
|
||||
result = subprocess.run(shell_cmd, shell=True, capture_output=True, text=True)
|
||||
|
||||
# Handle curl exit codes
|
||||
@@ -514,7 +516,7 @@ def lume_api_delete(
|
||||
"-s",
|
||||
"-X",
|
||||
"DELETE",
|
||||
f"'{api_url}'",
|
||||
api_url,
|
||||
]
|
||||
|
||||
# For logging and display, show the properly escaped URL
|
||||
@@ -537,7 +539,7 @@ def lume_api_delete(
|
||||
# Execute the command - for execution we need to use shell=True to handle URLs with special characters
|
||||
try:
|
||||
# Use a single string with shell=True for proper URL handling
|
||||
shell_cmd = " ".join(cmd)
|
||||
shell_cmd = safe_join(cmd)
|
||||
result = subprocess.run(shell_cmd, shell=True, capture_output=True, text=True)
|
||||
|
||||
# Handle curl exit codes
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
import shlex
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
import mslex
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
|
||||
@@ -104,3 +107,25 @@ def parse_vm_info(vm_info: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Parse VM info from pylume response."""
|
||||
if not vm_info:
|
||||
return None
|
||||
|
||||
|
||||
def safe_join(argv: list[str]) -> str:
|
||||
"""
|
||||
Return a platform-correct string that safely quotes `argv` for shell execution.
|
||||
|
||||
- On POSIX: uses `shlex.join`.
|
||||
- On Windows: uses `shlex.join`.
|
||||
|
||||
Args:
|
||||
argv: iterable of argument strings (will be coerced to str).
|
||||
|
||||
Returns:
|
||||
A safely quoted command-line string appropriate for the current platform that protects against
|
||||
shell injection vulnerabilities.
|
||||
"""
|
||||
if os.name == "nt":
|
||||
# On Windows, use mslex for proper quoting
|
||||
return mslex.join(argv)
|
||||
else:
|
||||
# On POSIX systems, use shlex
|
||||
return shlex.join(argv)
|
||||
|
||||
@@ -16,7 +16,8 @@ dependencies = [
|
||||
"websockets>=12.0",
|
||||
"aiohttp>=3.9.0",
|
||||
"cua-core>=0.1.0,<0.2.0",
|
||||
"pydantic>=2.11.1"
|
||||
"pydantic>=2.11.1",
|
||||
"mslex>=1.3.0",
|
||||
]
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -47,4 +48,4 @@ source-includes = ["tests/", "README.md", "LICENSE"]
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
testpaths = ["tests"]
|
||||
python_files = "test_*.py"
|
||||
python_files = "test_*.py"
|
||||
|
||||
17
uv.lock
generated
17
uv.lock
generated
@@ -861,7 +861,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "cua-agent"
|
||||
version = "0.4.35"
|
||||
version = "0.4.37"
|
||||
source = { editable = "libs/python/agent" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -1015,11 +1015,12 @@ provides-extras = ["openai", "anthropic", "qwen", "omni", "uitars", "uitars-mlx"
|
||||
|
||||
[[package]]
|
||||
name = "cua-computer"
|
||||
version = "0.4.10"
|
||||
version = "0.4.11"
|
||||
source = { editable = "libs/python/computer" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
{ name = "cua-core" },
|
||||
{ name = "mslex" },
|
||||
{ name = "pillow" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "websocket-client" },
|
||||
@@ -1046,6 +1047,7 @@ requires-dist = [
|
||||
{ name = "datasets", marker = "extra == 'ui'", specifier = ">=3.6.0" },
|
||||
{ name = "gradio", marker = "extra == 'all'", specifier = ">=5.23.3" },
|
||||
{ name = "gradio", marker = "extra == 'ui'", specifier = ">=5.23.3" },
|
||||
{ name = "mslex", specifier = ">=1.3.0" },
|
||||
{ name = "pillow", specifier = ">=10.0.0" },
|
||||
{ name = "pydantic", specifier = ">=2.11.1" },
|
||||
{ name = "python-dotenv", marker = "extra == 'all'", specifier = ">=1.0.1" },
|
||||
@@ -1057,7 +1059,7 @@ provides-extras = ["lume", "lumier", "ui", "all"]
|
||||
|
||||
[[package]]
|
||||
name = "cua-computer-server"
|
||||
version = "0.1.27"
|
||||
version = "0.1.28"
|
||||
source = { editable = "libs/python/computer-server" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -3430,6 +3432,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mslex"
|
||||
version = "1.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e0/97/7022667073c99a0fe028f2e34b9bf76b49a611afd21b02527fbfd92d4cd5/mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d", size = 11583, upload-time = "2024-10-16T13:16:18.523Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/f2/66bd65ca0139675a0d7b18f0bada6e12b51a984e41a76dbe44761bf1b3ee/mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4", size = 7820, upload-time = "2024-10-16T13:16:17.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multidict"
|
||||
version = "6.7.0"
|
||||
|
||||
Reference in New Issue
Block a user