🛡️ Sentinel: [CRITICAL] Fix environment leakage and sandbox bypass in unit test gate#329
Conversation
… unit test gate 🚨 Severity: CRITICAL 💡 Vulnerability: The scripts/03_unit_test_gate.py utility inherited the full environment, exposing secrets to executed code. Code wrapping logic was also broken, and bypass patterns were missing. 🎯 Impact: Potential exfiltration of sensitive API keys via generated code execution. 🔧 Fix: Filtered environment variables, fixed code indentation in template, and hardened dangerous pattern detection. ✅ Verification: Confirmed via reproduction scripts and full test suite.
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
There was a problem hiding this comment.
Code Review
This pull request implements security hardening measures and code refinements. It addresses environment variable leakage in the unit test gate by filtering subprocess environments and expands the detection of dangerous Python patterns. Additionally, it removes a thread-safe state cache in the telemetry engine and improves directory handling in JSONL saving utilities. Review feedback suggests further strengthening the security regex to include the builtins module and variants of dangerous os functions, while also noting a redundancy in the environment allowlist.
| r"\bimport\s+[^#\n]*\b(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc)\b", | ||
| r"\bfrom\s+(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc)\b", |
There was a problem hiding this comment.
The list of dangerous imports should include builtins. While you have blocked access to the __builtins__ attribute, an attacker could still use import builtins to access sensitive functions like eval or exec if they can bypass the other regex patterns (e.g., via builtins.__dict__).
| r"\bimport\s+[^#\n]*\b(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc)\b", | |
| r"\bfrom\s+(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc)\b", | |
| r"\bimport\s+[^#\n]*\b(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc|builtins)\b", | |
| r"\bfrom\s+(os|subprocess|sys|shutil|socket|requests|urllib|pathlib|pickle|pty|code|bdb|pdb|multiprocessing|threading|tempfile|ftplib|smtplib|telnetlib|http|xmlrpc|importlib|pkgutil|pydoc|builtins)\b", |
| r"\b__subclasses__\b", | ||
| # Dangerous module functions | ||
| r"\bos\.(system|popen|spawn|remove|unlink|rmdir|mkdir|chmod|chown|kill|exec|fork|pipe)\b", | ||
| r"\bos\.(system|popen|spawn|remove|unlink|rmdir|mkdir|chmod|chown|kill|exec|fork|pipe|environ)\b", |
There was a problem hiding this comment.
The regex for dangerous os functions is incomplete and easily bypassed.
- It misses
environb(the bytes version ofenviron),getenv, andputenv. - The use of
\baroundexecandspawnfails to catch common variants likeos.execv,os.execve,os.spawnv, etc., as\bdoes not match the transition between a word character and another word character (likev).
| r"\bos\.(system|popen|spawn|remove|unlink|rmdir|mkdir|chmod|chown|kill|exec|fork|pipe|environ)\b", | |
| r"\bos\.(system|popen|spawn\w*|remove|unlink|rmdir|mkdir|chmod|chown|kill|exec\w*|fork|pipe|environb?|getenv|putenv)\b", |
| allowed_env_keys = {"PATH", "PYTHONPATH", "LANG", "PYTHONIOENCODING"} | ||
| allowed_env = {k: os.environ[k] for k in allowed_env_keys if k in os.environ} | ||
| allowed_env["PYTHONPATH"] = temp_dir |
There was a problem hiding this comment.
Including PYTHONPATH in allowed_env_keys is redundant because it is immediately overwritten by temp_dir on line 272. For clarity and to avoid confusion about whether the parent's PYTHONPATH is being preserved, it should be removed from the allowlist if the intention is to strictly isolate the execution to the temporary directory.
| allowed_env_keys = {"PATH", "PYTHONPATH", "LANG", "PYTHONIOENCODING"} | |
| allowed_env = {k: os.environ[k] for k in allowed_env_keys if k in os.environ} | |
| allowed_env["PYTHONPATH"] = temp_dir | |
| allowed_env_keys = {"PATH", "LANG", "PYTHONIOENCODING"} | |
| allowed_env = {k: os.environ[k] for k in allowed_env_keys if k in os.environ} | |
| allowed_env["PYTHONPATH"] = temp_dir |
🛡️ Sentinel Security Fix
🚨 Severity: CRITICAL
💡 Vulnerability: The
scripts/03_unit_test_gate.pyscript was executing generated code samples while inheriting the entire environment of the parent process. This exposed sensitive credentials (e.g.,OPENAI_API_KEY,GITHUB_TOKEN) to potentially untrusted code. Furthermore, the script's code-wrapping logic was flawed, causingSyntaxErroron multi-line blocks, and it lacked protection against several common Python sandbox bypasses.🎯 Impact: Maliciously generated code could exfiltrate secrets or perform unauthorized actions using the pipeline's environment.
🔧 Fix:
test_python_codeto pass a strictly filtered environment (allowlist:PATH,PYTHONPATH,LANG,PYTHONIOENCODING) to the subprocess.textwrap.indentto ensure user code is correctly indented within the execution template, fixing a recurringSyntaxError.DANGEROUS_PATTERNSto blockimportlib,__builtins__,__globals__,__subclasses__, andos.environ.NameErrorinheidi_engine/telemetry.pyand aFileNotFoundErrorinsave_jsonlwhen writing to the current directory.✅ Verification:
if/for/defblocks now executes correctly.rufflinting checks passed.PR created automatically by Jules for task 10674563983628842377 started by @heidi-dang