Добавлен безопасный shell runner для workspace
Этот коммит содержится в:
@@ -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:],
|
||||
}
|
||||
Ссылка в новой задаче
Block a user