Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@
**Vulnerability:** Telemetry HTTP endpoints (`/status`, `/`) were completely unprotected, allowing any local user to view training state, usage, and costs.
**Learning:** Initial implementation prioritized ease of use and local-only binding (`127.0.0.1`) but neglected defense-in-depth requirements for multi-user or shared environments.
**Prevention:** Always implement at least Basic Authentication for any endpoint exposing state or metadata, even if restricted to loopback. Use random session-specific credentials if no configuration is provided.

## 2025-01-24 - Environment Leakage and Sandbox Escape in Unit Test Gate
**Vulnerability:** The unit test gatekeeper was passing the entire host environment to the subprocess executing generated code, and lacked checks for Python internal attributes like `__subclasses__`.
**Learning:** Even "optional" or "local" test scripts can become vectors for secret leakage (e.g., OPENAI_API_KEY) if they don't explicitly isolate the execution environment. Regex-based filtering is a baseline, but environment isolation is more robust.
**Prevention:** Always use a strict allowlist for environment variables when spawning subprocesses to execute untrusted or generated code. Include Python introspection attributes in blocklists for a basic defense-in-depth against sandbox escapes.
4 changes: 0 additions & 4 deletions heidi_engine/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,10 +732,6 @@ def get_state(run_id: Optional[str] = None) -> Dict[str, Any]:
"usage": get_default_usage(),
}

# BOLT OPTIMIZATION: Check thread-safe state cache
cached = _state_cache.get(target_run_id, state_file)
if cached:
return cached

try:
with open(state_file) as f:
Expand Down
15 changes: 13 additions & 2 deletions scripts/03_unit_test_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import subprocess
import sys
import tempfile
import textwrap
from typing import Any, Dict, List, Tuple

# =============================================================================
Expand Down Expand Up @@ -82,6 +83,10 @@
r"\bshutil\.(rmtree|move|copy|copy2|copyfile|copymode|copystat|chown)\b",
r"\bpickle\.(load|loads)\b",
r"\bshelve\.open\b",
# Internal attributes for sandbox escape
r"__subclasses__",
r"__globals__",
r"__builtins__",
# File operations (specifically writing/appending)
r"\bopen\s*\([^)]*,\s*(mode\s*=\s*)?['\"][^'\"r]*[wa+x]",
]
Expand Down Expand Up @@ -229,7 +234,7 @@ def test_python_code(code: str, temp_dir: str, execution_timeout: int = 5) -> Tu
sys.stderr = stderr_capture

# Execute the user's code
{code}
{textwrap.indent(code, ' ')}

sys.stdout = original_stdout
sys.stderr = original_stderr
Expand Down Expand Up @@ -257,13 +262,19 @@ def test_python_code(code: str, temp_dir: str, execution_timeout: int = 5) -> Tu

# Try to execute with timeout
try:
# BOLT SECURITY: Filter environment to prevent leakage of sensitive keys (e.g. OPENAI_API_KEY)
# to the generated code being tested.
allowed_env_keys = {"PATH", "PYTHONPATH", "LANG", "PYTHONIOENCODING"}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PYTHONPATH key in allowed_env_keys is redundant because it is explicitly overwritten on line 269. Removing it from the allowlist improves clarity and ensures that the host's PYTHONPATH is intentionally ignored in favor of the isolated temp_dir. Additionally, consider moving allowed_env_keys to a module-level constant to avoid recreating the set on every function call.

Suggested change
allowed_env_keys = {"PATH", "PYTHONPATH", "LANG", "PYTHONIOENCODING"}
allowed_env_keys = {"PATH", "LANG", "PYTHONIOENCODING"}

safe_env = {k: v for k, v in os.environ.items() if k in allowed_env_keys}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Environment variable keys can be case-insensitive on some platforms (like Windows). The current set lookup is case-sensitive, which might cause essential variables like Path (instead of PATH) to be filtered out, potentially breaking the subprocess execution. Using k.upper() for the check ensures cross-platform robustness.

Suggested change
safe_env = {k: v for k, v in os.environ.items() if k in allowed_env_keys}
safe_env = {k: v for k, v in os.environ.items() if k.upper() in allowed_env_keys}

safe_env["PYTHONPATH"] = temp_dir # Ensure isolation and local imports

result = subprocess.run(
[sys.executable, test_file],
capture_output=True,
text=True,
timeout=execution_timeout,
cwd=temp_dir,
env={**os.environ, "PYTHONPATH": temp_dir},
env=safe_env,
)

stdout = result.stdout
Expand Down