Добавлен безопасный shell runner для workspace

Этот коммит содержится в:
Виктор
2026-05-11 22:43:43 +09:00
родитель f5924011b5
Коммит c0939481b6
+57
Просмотреть файл
@@ -0,0 +1,57 @@
import os
import subprocess
from pathlib import Path
DATA_DIR = Path(os.getenv('DEVCONSOLE_DATA_DIR', '/var/lib/devconsole'))
PROJECTS_DIR = DATA_DIR / 'projects'
BLOCKED_TOKENS = [
'rm -rf /',
'mkfs',
':(){',
'dd if=',
'shutdown',
'reboot',
'poweroff',
]
def _is_inside_projects(path: Path) -> bool:
try:
path.resolve().relative_to(PROJECTS_DIR.resolve())
return True
except ValueError:
return False
def run_command(command: str, cwd: str | None = None, timeout: int = 900) -> dict:
if not command.strip():
raise ValueError('Command is empty')
lowered = command.lower()
for token in BLOCKED_TOKENS:
if token in lowered:
raise ValueError(f'Blocked unsafe command: {token}')
workdir = Path(cwd or PROJECTS_DIR).resolve()
PROJECTS_DIR.mkdir(parents=True, exist_ok=True)
if not _is_inside_projects(workdir):
raise ValueError('Command cwd must be inside DevConsole projects directory')
process = subprocess.run(
command,
cwd=workdir,
shell=True,
text=True,
capture_output=True,
timeout=timeout,
)
return {
'command': command,
'cwd': workdir.as_posix(),
'returncode': process.returncode,
'stdout': process.stdout[-20000:],
'stderr': process.stderr[-20000:],
}