mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-16 16:36:53 +08:00
fix: sanitize subprocess call in runner.py (#2149)
* fix: V-001 security vulnerability Automated security fix generated by OrbisAI Security * fix: sanitize subprocess call in runner.py The runner * fix: address PR review comments on V-001 allowlist and test coverage Remove dangerous interpreters (python, python3, node, curl, wget) from ALLOWED_SETUP_EXECUTABLES — they can execute arbitrary code via argument flags and are not needed for sandbox setup. Rewrite test_invariant_runner to call _setup_sandbox directly instead of spawning runner.py as a subprocess (which had no __main__ entrypoint and never exercised the fix). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1c3280dc0d
commit
cf59d0d283
@ -15,6 +15,11 @@ from scripts.scenario_generator import Scenario
|
||||
|
||||
SANDBOX_BASE = Path("/tmp/skill-comply-sandbox")
|
||||
ALLOWED_MODELS = frozenset({"haiku", "sonnet", "opus"})
|
||||
ALLOWED_SETUP_EXECUTABLES = frozenset({
|
||||
"git", "npm", "pip", "pip3",
|
||||
"touch", "mkdir", "cp", "mv", "echo",
|
||||
"chmod", "unzip", "tar",
|
||||
})
|
||||
# Shell builtins cannot be invoked via subprocess.run; cwd is already
|
||||
# controlled by the cwd= keyword. Scenarios that include these in
|
||||
# setup_commands (a common shell-style convention) must be tolerated.
|
||||
@ -106,6 +111,9 @@ def _setup_sandbox(sandbox_dir: Path, scenario: Scenario) -> None:
|
||||
if not parts or parts[0] in SHELL_BUILTINS:
|
||||
# Shell builtins (cd/pushd/popd) cannot run as subprocess; skip.
|
||||
continue
|
||||
if parts[0] not in ALLOWED_SETUP_EXECUTABLES:
|
||||
# Restrict to known-safe executables to prevent arbitrary code execution.
|
||||
continue
|
||||
try:
|
||||
subprocess.run(parts, cwd=sandbox_dir, capture_output=True)
|
||||
except FileNotFoundError:
|
||||
|
||||
64
tests/test_invariant_runner.py
Normal file
64
tests/test_invariant_runner.py
Normal file
@ -0,0 +1,64 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
_SKILL_COMPLY_ROOT = Path(__file__).resolve().parent.parent / "skills" / "skill-comply"
|
||||
if str(_SKILL_COMPLY_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(_SKILL_COMPLY_ROOT))
|
||||
|
||||
from scripts.runner import _setup_sandbox # noqa: E402
|
||||
from scripts.scenario_generator import Scenario # noqa: E402
|
||||
|
||||
_GLOBAL_MARKER = "/tmp/runner_test_pwned_marker"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _remove_marker():
|
||||
if os.path.exists(_GLOBAL_MARKER):
|
||||
os.remove(_GLOBAL_MARKER)
|
||||
yield
|
||||
if os.path.exists(_GLOBAL_MARKER):
|
||||
os.remove(_GLOBAL_MARKER)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"setup_commands,test_id",
|
||||
[
|
||||
(
|
||||
("python -c \"import os; os.system('touch /tmp/runner_test_pwned_marker')\"",),
|
||||
"python_interpreter",
|
||||
),
|
||||
(
|
||||
("../../../../../../bin/sh -c 'touch /tmp/runner_test_pwned_marker'",),
|
||||
"path_traversal",
|
||||
),
|
||||
(
|
||||
("bash -c 'touch /tmp/runner_test_pwned_marker'",),
|
||||
"non_allowlisted_binary",
|
||||
),
|
||||
(
|
||||
("echo hello",),
|
||||
"benign_echo",
|
||||
),
|
||||
],
|
||||
ids=["python_interpreter", "path_traversal", "non_allowlisted_binary", "benign_echo"],
|
||||
)
|
||||
def test_setup_sandbox_blocks_dangerous_commands(setup_commands, test_id, tmp_path):
|
||||
"""Invariant: _setup_sandbox must not execute disallowed commands."""
|
||||
scenario = Scenario(
|
||||
id=f"test-{test_id}",
|
||||
level=1,
|
||||
level_name="basic",
|
||||
description="security test scenario",
|
||||
prompt="",
|
||||
setup_commands=setup_commands,
|
||||
)
|
||||
sandbox_dir = tmp_path / "sandbox"
|
||||
|
||||
_setup_sandbox(sandbox_dir, scenario)
|
||||
|
||||
assert not os.path.exists(_GLOBAL_MARKER), (
|
||||
f"Arbitrary command execution detected for '{test_id}': "
|
||||
f"marker file created at {_GLOBAL_MARKER}"
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user