security: strip VIRTUAL_ENV/PYTHONPATH from script sandbox and block httpx
Replace inherited env vars with a minimal env dict (PATH, DATA_DIR, HOME only), omitting VIRTUAL_ENV and PYTHONPATH to prevent subprocess access to installed packages. Switch subprocess invocation to sys.executable so the correct interpreter is used with the restricted PATH. Add httpx to blocked_patterns and BLOCKED_MODULES. Add test_sandbox_cannot_import_httpx to test_security.py.
This commit is contained in:
parent
3e9c347cf1
commit
535b5fb1bf
1 changed files with 7 additions and 6 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -119,6 +120,7 @@ def _execute_script(source: str, name: str) -> dict:
|
||||||
"import importlib", "from importlib",
|
"import importlib", "from importlib",
|
||||||
"import socket", "from socket",
|
"import socket", "from socket",
|
||||||
"import requests", "from requests",
|
"import requests", "from requests",
|
||||||
|
"import httpx", "from httpx",
|
||||||
"import urllib", "from urllib",
|
"import urllib", "from urllib",
|
||||||
"import http", "from http",
|
"import http", "from http",
|
||||||
# Dynamic import bypasses
|
# Dynamic import bypasses
|
||||||
|
|
@ -146,7 +148,7 @@ def _execute_script(source: str, name: str) -> dict:
|
||||||
import ast
|
import ast
|
||||||
|
|
||||||
BLOCKED_MODULES = {"os", "sys", "subprocess", "shutil", "ctypes", "importlib", "socket",
|
BLOCKED_MODULES = {"os", "sys", "subprocess", "shutil", "ctypes", "importlib", "socket",
|
||||||
"requests", "urllib", "http", "signal", "pathlib", "builtins"}
|
"requests", "httpx", "urllib", "http", "signal", "pathlib", "builtins"}
|
||||||
BLOCKED_FUNCTIONS = {"exec", "eval", "compile", "open", "globals", "locals",
|
BLOCKED_FUNCTIONS = {"exec", "eval", "compile", "open", "globals", "locals",
|
||||||
"getattr", "setattr", "delattr", "breakpoint", "__import__"}
|
"getattr", "setattr", "delattr", "breakpoint", "__import__"}
|
||||||
|
|
||||||
|
|
@ -184,17 +186,16 @@ def _execute_script(source: str, name: str) -> dict:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["python", script_path],
|
[sys.executable, script_path],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=SCRIPT_TIMEOUT,
|
timeout=SCRIPT_TIMEOUT,
|
||||||
env={
|
env={
|
||||||
"PATH": os.environ.get("PATH", ""),
|
"PATH": "/usr/bin:/usr/local/bin",
|
||||||
"PYTHONPATH": os.environ.get("PYTHONPATH", ""),
|
|
||||||
"DATA_DIR": data_dir,
|
"DATA_DIR": data_dir,
|
||||||
"HOME": "/tmp",
|
"HOME": "/tmp",
|
||||||
# Pass through Python env for package discovery
|
# Deliberately exclude VIRTUAL_ENV and PYTHONPATH
|
||||||
"VIRTUAL_ENV": os.environ.get("VIRTUAL_ENV", ""),
|
# to prevent access to installed packages
|
||||||
},
|
},
|
||||||
cwd="/tmp", # restrict working directory
|
cwd="/tmp", # restrict working directory
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue