# SPDX-License-Identifier: AGPL-3.0-only # Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 """Tests for Bypass Permissions (skip confirmation + disable sandbox). Covers the secret-name classifier, the two env builders, the ``disable_sandbox`` branch of ``_python_exec`` / ``_bash_exec`` (which env is used, which pre-exec is used, and that safety checks / the blocklist are skipped), the request-model default, the confirm-vs-bypass precedence rule the route enforces, and that the agentic loop forwards ``disable_sandbox`` while never gating under bypass. Run with: ``PYTHONPATH=studio/backend python -m pytest studio/backend/tests/test_bypass_permissions.py -q`` """ import os import sys import pytest import core.inference.tools as tools from core.inference.tools import ( _bash_exec, _build_bypass_env, _build_safe_env, _is_cred_location_env_name, _is_secret_env_name, _is_secret_env_value, _python_exec, ) from core.inference.safetensors_agentic import run_safetensors_tool_loop _POSIX_ONLY = pytest.mark.skipif( sys.platform == "win32", reason = "preexec_fn / setsid are POSIX-only" ) # ── secret-name classifier ────────────────────────────────────────── @pytest.mark.parametrize( "name", [ "HF_TOKEN", "HUGGING_FACE_HUB_TOKEN", "WANDB_API_KEY", "GH_TOKEN", "GITHUB_TOKEN", "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "AWS_SECRET_ACCESS_KEY", "AWS_ACCESS_KEY_ID", "AZURE_CLIENT_SECRET", "GOOGLE_APPLICATION_CREDENTIALS", "MY_DB_PASSWORD", "x_api_key", "SOME_PRIVATE_KEY", "LD_PRELOAD", ], ) def test_secret_names_are_flagged(name): assert _is_secret_env_name(name) is True @pytest.mark.parametrize( "name", ["PATH", "HOME", "LANG", "TERM", "PWD", "SHELL", "HOSTVAR", "MY_VAR"] ) def test_benign_names_are_not_flagged(name): assert _is_secret_env_name(name) is False # ── env builders ──────────────────────────────────────────────────── def test_bypass_env_keeps_benign_strips_secret_repoints_home(monkeypatch, tmp_path): monkeypatch.setenv("HOSTVAR", "benign-123") monkeypatch.setenv("HF_TOKEN", "secret-abc") env = _build_bypass_env(str(tmp_path)) assert env.get("HOSTVAR") == "benign-123" # full host env inherited assert "HF_TOKEN" not in env # ...minus secrets assert env["HOME"] == str(tmp_path) # $HOME-based cred lookups defused assert env["TMPDIR"] == str(tmp_path) def test_safe_env_excludes_host_and_secret(monkeypatch, tmp_path): monkeypatch.setenv("HOSTVAR", "benign-123") monkeypatch.setenv("HF_TOKEN", "secret-abc") env = _build_safe_env(str(tmp_path)) assert "HOSTVAR" not in env # whitelist build -> host vars never reach child assert "HF_TOKEN" not in env # ── Popen kwargs capture (no real execution) ──────────────────────── class _FakeProc: returncode = 0 def communicate(self, timeout = None): return ("FAKEOUT", None) def poll(self): return 0 def kill(self): pass @pytest.fixture def captured_popen(monkeypatch): cap = {} def fake_popen(cmd, **kwargs): cap["cmd"] = cmd cap["kwargs"] = kwargs return _FakeProc() monkeypatch.setattr(tools.subprocess, "Popen", fake_popen) return cap @_POSIX_ONLY def test_python_sandboxed_uses_sandbox_preexec_and_safe_env(captured_popen, monkeypatch): monkeypatch.setenv("HF_TOKEN", "secret-abc") _python_exec("print(1)", None, 5, "t", disable_sandbox = False) assert captured_popen["kwargs"]["preexec_fn"] is tools._sandbox_preexec assert "HF_TOKEN" not in captured_popen["kwargs"]["env"] @_POSIX_ONLY def test_python_bypass_uses_bypass_preexec_and_bypass_env(captured_popen, monkeypatch): monkeypatch.setenv("HOSTVAR", "benign-xyz") monkeypatch.setenv("HF_TOKEN", "secret-abc") _python_exec("print(1)", None, 5, "t", disable_sandbox = True) assert captured_popen["kwargs"]["preexec_fn"] is tools._bypass_preexec env = captured_popen["kwargs"]["env"] assert env.get("HOSTVAR") == "benign-xyz" assert env.get("PYTHONIOENCODING") == "utf-8" assert "HF_TOKEN" not in env def test_bash_blocklist_enforced_when_sandboxed(captured_popen): out = _bash_exec("rm -rf /", None, 5, "t", disable_sandbox = False) assert "Blocked" in out assert "cmd" not in captured_popen # never reached Popen def test_bash_blocklist_skipped_when_bypassed(captured_popen): out = _bash_exec("rm -rf /", None, 5, "t", disable_sandbox = True) assert out == "FAKEOUT" # blocklist skipped -> reached (faked) execution assert captured_popen["cmd"][0] in ("bash", "cmd") @_POSIX_ONLY def test_bash_bypass_uses_bypass_preexec(captured_popen, monkeypatch): # bypass inherits benign host vars; clear so we assert _bash_exec adds none. monkeypatch.delenv("PYTHONIOENCODING", raising = False) _bash_exec("echo hi", None, 5, "t", disable_sandbox = True) assert captured_popen["kwargs"]["preexec_fn"] is tools._bypass_preexec assert "PYTHONIOENCODING" not in captured_popen["kwargs"]["env"] # ── real end-to-end python execution under bypass ─────────────────── @_POSIX_ONLY def test_python_bypass_real_exec_sees_host_env_but_not_secret(monkeypatch): monkeypatch.setenv("HOSTVAR", "benign-xyz") monkeypatch.setenv("HF_TOKEN", "secret-pqr") code = ( "import os;" "print('H=' + str(os.environ.get('HOSTVAR'))," " 'T=' + str(os.environ.get('HF_TOKEN')))" ) out = _python_exec(code, None, 30, "test-bypass", disable_sandbox = True) assert "H=benign-xyz" in out # unrestricted: real host var visible assert "T=None" in out # ...but the secret was stripped assert "secret-pqr" not in out # ── _bypass_preexec is setsid-only (no rlimits) ───────────────────── @_POSIX_ONLY def test_bypass_preexec_only_sets_session(monkeypatch): calls = {"setsid": 0} monkeypatch.setattr( tools.os, "setsid", lambda: calls.__setitem__("setsid", calls["setsid"] + 1) ) # _resource must not be touched by the bypass pre-exec. if tools._resource is not None: monkeypatch.setattr( tools._resource, "setrlimit", lambda *a, **k: pytest.fail("bypass pre-exec must not set rlimits"), ) tools._bypass_preexec() assert calls["setsid"] == 1 # ── request model default ─────────────────────────────────────────── def test_request_model_bypass_default_false(): from models.inference import ChatCompletionRequest assert ChatCompletionRequest.model_fields["bypass_permissions"].default is False # ── confirm-vs-bypass precedence (mirrors the route rule) ─────────── @pytest.mark.parametrize( "confirm,bypass,effective_confirm", [ (False, False, False), (True, False, True), (False, True, False), (True, True, False), ], ) def test_confirm_precedence_rule(confirm, bypass, effective_confirm): # The route computes: confirm_tool_calls = confirm and not bypass. assert (bool(confirm) and not bool(bypass)) is effective_confirm # ── agentic loop forwards disable_sandbox, never gates under bypass ── _DEFAULT_TOOLS = [ {"type": "function", "function": {"name": "python"}}, {"type": "function", "function": {"name": "web_search"}}, ] def _tool_call(name, args_json): return f'{{"name": "{name}", "arguments": {args_json}}}' def _multi_turn(turns): it = iter(turns) def _gen(_messages): try: yield next(it) except StopIteration: return return _gen def test_loop_forwards_disable_sandbox_and_does_not_gate(): seen = [] def fake_exec( name, arguments, *, cancel_event = None, timeout = None, session_id = None, rag_scope = None, disable_sandbox = False, ): seen.append(disable_sandbox) return f"RAN[{name}]" events = list( run_safetensors_tool_loop( single_turn = _multi_turn([_tool_call("python", '{"code": "x"}'), "done"]), messages = [{"role": "user", "content": "hi"}], tools = _DEFAULT_TOOLS, execute_tool = fake_exec, session_id = "s", confirm_tool_calls = False, # route forces this off under bypass bypass_permissions = True, ) ) assert seen == [True] # disable_sandbox threaded through starts = [e for e in events if e["type"] == "tool_start"] assert starts and starts[0]["awaiting_confirmation"] is False assert starts[0]["approval_id"] == "" def test_loop_bypass_overrides_confirm_for_direct_callers(): # Even if a direct internal caller passes confirm_tool_calls=True, bypass # must suppress the confirm gate at the loop level (not only at the route). def fake_exec( name, arguments, *, cancel_event = None, timeout = None, session_id = None, rag_scope = None, disable_sandbox = False, ): return f"RAN[{name}]" events = list( run_safetensors_tool_loop( single_turn = _multi_turn([_tool_call("python", '{"code": "x"}'), "done"]), messages = [{"role": "user", "content": "hi"}], tools = _DEFAULT_TOOLS, execute_tool = fake_exec, session_id = "s", confirm_tool_calls = True, # raw caller leaves this on... bypass_permissions = True, # ...but bypass must still win ) ) starts = [e for e in events if e["type"] == "tool_start"] assert starts and starts[0]["awaiting_confirmation"] is False assert starts[0]["approval_id"] == "" def test_gguf_loop_confirm_gate_respects_bypass(): # The GGUF loop needs a live llama-server, so (per the other llama_cpp # tests) assert via AST that its _needs_confirm gate applies the bypass # precedence, mirroring the safetensors behavioral test above. import ast import inspect import textwrap llama_cpp = pytest.importorskip("core.inference.llama_cpp") src = textwrap.dedent( inspect.getsource(llama_cpp.LlamaCppBackend.generate_chat_completion_with_tools) ) gates = [ node for node in ast.walk(ast.parse(src)) if isinstance(node, ast.Assign) and any(getattr(t, "id", None) == "needs_confirm" for t in node.targets) ] assert gates, "could not find the needs_confirm gate in the GGUF loop" names = {n.id for g in gates for n in ast.walk(g.value) if isinstance(n, ast.Name)} assert "confirm_tool_calls" in names assert "bypass_permissions" in names # bypass must suppress the GGUF gate # ── broker / capability env vars are stripped (regression) ────────── @pytest.mark.parametrize( "name", ["SSH_AUTH_SOCK", "SSH_AGENT_PID", "GPG_AGENT_INFO", "GNUPGHOME", "KUBECONFIG"], ) def test_broker_capability_names_are_flagged(name): # Not secrets by value, but they hand the child the operator's live agent # (ssh/gpg) or kube credentials, so bypass mode must drop them. assert _is_secret_env_name(name) is True # ── credential-bearing URL values stripped regardless of name ─────── @pytest.mark.parametrize( "value", [ "https://user:s3cr3t@feed.example.invalid/simple", # user:pass@ "https://ghp_deadbeef@github.com/org/private.git", # token-only@ "https://__token__@pypi.example.invalid/simple", "https://ghp_1234:@npm.pkg.github.com/simple", # empty password "postgres://dbuser:dbpass@db.example.invalid/app", ], ) def test_url_userinfo_values_are_flagged(value): assert _is_secret_env_value(value) is True @pytest.mark.parametrize( "value", [ "https://example.invalid/simple", # no userinfo "http://proxy.corp.example:8080", # benign proxy "https://pypi.corp.example/simple", # benign internal index "redis://localhost:6379/0", # no creds "https://example.invalid/path?ref=a@b", # '@' only in query, not userinfo ], ) def test_non_credential_url_values_are_not_flagged(value): assert _is_secret_env_value(value) is False def test_url_userinfo_value_is_stripped_even_with_benign_name(monkeypatch, tmp_path): # NAME dodges the classifier, but the VALUE embeds userinfo -> must go. monkeypatch.setenv("MY_FEED", "https://user:s3cr3t@feed.example.invalid/simple") monkeypatch.setenv("REPO_URL", "https://ghp_deadbeef@github.com/org/private.git") # A URL without credentials is harmless and should be kept. monkeypatch.setenv("PLAIN_URL", "https://example.invalid/simple") env = _build_bypass_env(str(tmp_path)) assert "MY_FEED" not in env assert "REPO_URL" not in env assert env.get("PLAIN_URL") == "https://example.invalid/simple" def test_bypass_env_keeps_noncredential_proxy_and_index_urls(monkeypatch, tmp_path): # Benign routing/config vars must survive bypass mode (proxy-only or # internal-index networks); only credentialed values are dropped. monkeypatch.setenv("HTTP_PROXY", "http://proxy.corp.example:8080") monkeypatch.setenv("PIP_INDEX_URL", "https://pypi.corp.example/simple") monkeypatch.setenv("PIP_EXTRA_INDEX_URL", "https://user:token@pypi.example.invalid/simple") env = _build_bypass_env(str(tmp_path)) assert env["HTTP_PROXY"] == "http://proxy.corp.example:8080" assert env["PIP_INDEX_URL"] == "https://pypi.corp.example/simple" assert "PIP_EXTRA_INDEX_URL" not in env # this one carries credentials # ── AWS IMDS-disable hardening flag is kept (regression) ──────────── def test_aws_imds_disable_flag_is_kept_but_creds_stripped(monkeypatch, tmp_path): # AWS_EC2_METADATA_DISABLED is a non-secret opt-out: dropping it would let a # bypassed boto/AWS-CLI call fall back to the instance role via IMDS even # though the operator disabled that path. Keep it; drop the real creds. monkeypatch.setenv("AWS_EC2_METADATA_DISABLED", "true") monkeypatch.setenv("AWS_ACCESS_KEY_ID", "AKIAEXAMPLE") monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "shhh") assert _is_secret_env_name("AWS_EC2_METADATA_DISABLED") is False assert _is_secret_env_name("AWS_ACCESS_KEY_ID") is True env = _build_bypass_env(str(tmp_path)) assert env.get("AWS_EC2_METADATA_DISABLED") == "true" assert "AWS_ACCESS_KEY_ID" not in env assert "AWS_SECRET_ACCESS_KEY" not in env # ── connection-string env vars are stripped (regression) ──────────── @pytest.mark.parametrize( "name", [ "SQLCONNSTR_DB", # Azure App Service injected connection strings "MYSQLCONNSTR_DB", "SQLAZURECONNSTR_DB", "POSTGRESQLCONNSTR_DB", "CUSTOMCONNSTR_CACHE", "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", ], ) def test_connection_string_names_are_flagged(name): assert _is_secret_env_name(name) is True @pytest.mark.parametrize( "value", [ "Server=tcp:db;Database=app;User ID=u;Password=p@ss;", # ADO.NET "DefaultEndpointsProtocol=https;AccountName=x;AccountKey=abc123==;", # storage "Endpoint=sb://x;SharedAccessKeyName=n;SharedAccessKey=zzz=", # Service Bus ], ) def test_connection_string_values_are_flagged(value): assert _is_secret_env_value(value) is True @pytest.mark.parametrize( "value", [ "Server=tcp:db;Database=app;User ID=u;", # no password field "Endpoint=sb://x;SharedAccessKeyName=n", # key NAME only, no secret "AccountName=x;EndpointSuffix=core.windows.net", # no AccountKey ], ) def test_connection_string_noncredential_values_are_not_flagged(value): assert _is_secret_env_value(value) is False def test_connection_string_value_stripped_even_with_benign_name(monkeypatch, tmp_path): # NAME dodges the classifier, but the VALUE is a credentialed conn string. monkeypatch.setenv("APP_DB", "Server=tcp:db;Database=app;User ID=u;Password=p@ss;") monkeypatch.setenv("SQLCONNSTR_DB", "DefaultEndpointsProtocol=https;AccountKey=abc==") env = _build_bypass_env(str(tmp_path)) assert "APP_DB" not in env # value-based catch assert "SQLCONNSTR_DB" not in env # name-based catch # ── temp dirs repointed on every platform (regression) ────────────── def test_bypass_env_repoints_all_temp_vars(monkeypatch, tmp_path): # Windows tempfile honours TEMP/TMP, not TMPDIR; all three must repoint. monkeypatch.setenv("TEMP", "/host/tmp") monkeypatch.setenv("TMP", "/host/tmp") env = _build_bypass_env(str(tmp_path)) assert env["TMPDIR"] == str(tmp_path) assert env["TEMP"] == str(tmp_path) assert env["TMP"] == str(tmp_path) # ── credential-location redirect vars are dropped (regression) ────────── # Vars that point SDKs at the real home/cache/config (cached tokens), e.g. # HF_HOME which startup always sets -> the live leak the HOME repoint missed. @pytest.mark.parametrize( "name", [ "HF_HOME", "HF_HUB_CACHE", "HUGGINGFACE_HUB_CACHE", "HF_XET_CACHE", "TRANSFORMERS_CACHE", "HF_DATASETS_CACHE", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "XDG_DATA_HOME", "NETRC", "BOTO_CONFIG", "PIP_CONFIG_FILE", "CLOUDSDK_CONFIG", "KAGGLE_CONFIG_DIR", "DOCKER_CONFIG", "WANDB_DIR", "WANDB_CONFIG_DIR", "NPM_CONFIG_USERCONFIG", "NPM_CONFIG_GLOBALCONFIG", "YARN_RC_FILENAME", "GIT_CONFIG_GLOBAL", "GIT_CONFIG_SYSTEM", "CARGO_HOME", "RCLONE_CONFIG", "GIT_ASKPASS", "SSH_ASKPASS", "BASH_ENV", "HOMEDRIVE", "HOMEPATH", ], ) def test_cred_location_names_are_flagged(name): assert _is_cred_location_env_name(name) is True @pytest.mark.parametrize("name", ["PATH", "HOME", "LANG", "PWD", "MY_VAR"]) def test_benign_names_not_flagged_as_cred_location(name): assert _is_cred_location_env_name(name) is False def test_bypass_env_drops_hf_home_so_cached_token_unreachable(monkeypatch, tmp_path): # The live leak: startup sets HF_HOME at the real cache, whose $HF_HOME/token # holds the operator's token. Repointing HOME does not stop huggingface_hub # from reading $HF_HOME/token, so HF_HOME must be dropped in bypass mode. real_cache = tmp_path / "real_hf_cache" real_cache.mkdir() (real_cache / "token").write_text("hf_cachedOperatorToken") monkeypatch.setenv("HF_HOME", str(real_cache)) monkeypatch.setenv("HF_HUB_CACHE", str(real_cache / "hub")) env = _build_bypass_env(str(tmp_path)) assert "HF_HOME" not in env # dropped -> HF falls back to $HOME/.cache (empty) assert "HF_HUB_CACHE" not in env def test_bypass_env_hf_token_resolves_outside_real_cache(monkeypatch, tmp_path): # End-to-end: even when HF_HOME and XDG_CACHE_HOME both point at the real # cache, the bypass env must make huggingface_hub resolve the token under the # workdir (guards the XDG fallback chain, not just "HF_HOME absent"). pytest.importorskip("huggingface_hub") import subprocess real_cache = tmp_path / "real_hf" real_cache.mkdir() workdir = tmp_path / "sandbox" workdir.mkdir() monkeypatch.setenv("HF_HOME", str(real_cache)) monkeypatch.setenv("XDG_CACHE_HOME", str(real_cache)) monkeypatch.setenv("XDG_CONFIG_HOME", str(real_cache)) env = _build_bypass_env(str(workdir)) token_path = subprocess.run( [ sys.executable, "-c", "import huggingface_hub.constants as c; print(c.HF_TOKEN_PATH)", ], env = env, capture_output = True, text = True, ).stdout.strip() assert str(real_cache) not in token_path # never the operator's cache assert token_path.startswith(str(workdir)) # resolved under the sandbox def test_bypass_env_drops_credential_config_path_vars(monkeypatch, tmp_path): # NETRC / BOTO_CONFIG / PIP_CONFIG_FILE point clients at real credential # files before $HOME, so they must not survive into the bypassed child. monkeypatch.setenv("NETRC", "/home/op/.netrc") monkeypatch.setenv("PGPASSFILE", "/home/op/.pgpass") monkeypatch.setenv("BOTO_CONFIG", "/home/op/.boto") monkeypatch.setenv("PIP_CONFIG_FILE", "/home/op/.pip/pip.conf") env = _build_bypass_env(str(tmp_path)) assert "NETRC" not in env assert "PGPASSFILE" not in env assert "BOTO_CONFIG" not in env assert "PIP_CONFIG_FILE" not in env def test_bypass_env_strips_npm_auth_and_mysql_pwd(monkeypatch, tmp_path): # NPM_CONFIG__AUTH (npm _auth, base64) and MYSQL_PWD dodge the URL-value # check and the PASSWD marker, but must still be dropped. monkeypatch.setenv("NPM_CONFIG__AUTH", "aGVsbG86c2VjcmV0") monkeypatch.setenv("MYSQL_PWD", "db-password") assert _is_secret_env_name("NPM_CONFIG__AUTH") is True assert _is_secret_env_name("MYSQL_PWD") is True env = _build_bypass_env(str(tmp_path)) assert "NPM_CONFIG__AUTH" not in env assert "MYSQL_PWD" not in env @_POSIX_ONLY def test_bash_bypass_does_not_source_bash_env(monkeypatch, tmp_path): # bash -c sources $BASH_ENV for non-interactive shells; an operator startup # file could re-export stripped secrets, so a real bypass call must not see it. startup = tmp_path / "startup.sh" startup.write_text("export RECOVERED=leaked\n") monkeypatch.setenv("BASH_ENV", str(startup)) out = _bash_exec("echo R=$RECOVERED", None, 30, "bash-env-test", disable_sandbox = True) assert "R=leaked" not in out # BASH_ENV dropped -> startup not sourced assert "R=" in out def test_bypass_env_repoints_windows_profile_vars(monkeypatch, tmp_path): # On Windows, SDKs read cached creds under USERPROFILE/APPDATA/LOCALAPPDATA, # not $HOME. Set ones are repointed at the workdir; HOMEDRIVE/HOMEPATH drop. monkeypatch.setenv("USERPROFILE", "/host/profile") monkeypatch.setenv("APPDATA", "/host/profile/AppData/Roaming") monkeypatch.setenv("LOCALAPPDATA", "/host/profile/AppData/Local") monkeypatch.setenv("HOMEDRIVE", "C:") monkeypatch.setenv("HOMEPATH", "\\Users\\op") env = _build_bypass_env(str(tmp_path)) assert env["USERPROFILE"] == str(tmp_path) assert env["APPDATA"] == str(tmp_path) assert env["LOCALAPPDATA"] == str(tmp_path) assert "HOMEDRIVE" not in env assert "HOMEPATH" not in env def test_bypass_env_does_not_add_unset_windows_profile_vars(monkeypatch, tmp_path): # Only repoint Windows profile vars that were actually set (no pollution on # Linux/macOS where they are absent). monkeypatch.delenv("USERPROFILE", raising = False) monkeypatch.delenv("APPDATA", raising = False) monkeypatch.delenv("LOCALAPPDATA", raising = False) env = _build_bypass_env(str(tmp_path)) assert "USERPROFILE" not in env assert "APPDATA" not in env assert "LOCALAPPDATA" not in env # ── parent /proc env-leak hardening (regression) ──────────────────── @_POSIX_ONLY def test_bypass_exec_hardens_parent_proc_env(monkeypatch, captured_popen): # Stripping the child env is not enough: a same-UID child can read the # parent's /proc environ. The exec paths must invoke the parent hardening # when (and only when) the sandbox is disabled. calls = {"n": 0} def fake_harden(): calls["n"] += 1 return True monkeypatch.setattr(tools, "_harden_parent_against_proc_env_leak", fake_harden) _python_exec("print(1)", None, 5, "t", disable_sandbox = True) _bash_exec("echo hi", None, 5, "t", disable_sandbox = True) assert calls["n"] == 2 calls["n"] = 0 _python_exec("print(1)", None, 5, "t", disable_sandbox = False) _bash_exec("echo hi", None, 5, "t", disable_sandbox = False) assert calls["n"] == 0 # never hardened on the sandboxed path def test_bypass_exec_fails_closed_when_hardening_fails(monkeypatch, captured_popen): # If the parent cannot be hardened (e.g. prctl denied), the unsandboxed # child must NOT run - otherwise the parent environ stays readable. monkeypatch.setattr(tools, "_harden_parent_against_proc_env_leak", lambda: False) out_py = _python_exec("print(1)", None, 5, "t", disable_sandbox = True) out_sh = _bash_exec("echo hi", None, 5, "t", disable_sandbox = True) assert "refusing bypass execution" in out_py assert "refusing bypass execution" in out_sh assert "cmd" not in captured_popen # never reached Popen @_POSIX_ONLY def test_proc_env_unreadable_after_hardening(): # Mechanism check: after hardening, a same-UID child can no longer read the # parent process /proc environ. Restores the dumpable flag afterwards so the # process-global state does not leak into later tests. import subprocess if tools._libc is None: pytest.skip("no libc/prctl available") pid = os.getpid() probe = ( "try:\n" f" open('/proc/{pid}/environ', 'rb').read()\n" " print('READABLE')\n" "except PermissionError:\n" " print('DENIED')\n" ) prev_dumpable = tools._libc.prctl(3, 0, 0, 0, 0) # PR_GET_DUMPABLE prev_guard = tools._parent_proc_hardened try: # Establish a clean readable baseline: another test may have already # cleared the dumpable flag on this process. tools._libc.prctl(4, 1, 0, 0, 0) # PR_SET_DUMPABLE = 1 before = subprocess.run( [sys.executable, "-c", probe], capture_output = True, text = True ).stdout.strip() if before != "READABLE": pytest.skip("/proc already restricted in this environment") tools._parent_proc_hardened = False assert tools._harden_parent_against_proc_env_leak() is True after = subprocess.run( [sys.executable, "-c", probe], capture_output = True, text = True ).stdout.strip() assert after == "DENIED" finally: if prev_dumpable in (0, 1): try: tools._libc.prctl(4, prev_dumpable, 0, 0, 0) except (OSError, AttributeError): pass tools._parent_proc_hardened = prev_guard # ── Anthropic request model declares the field (regression) ───────── def test_anthropic_request_model_bypass_default_false(): # Omitting the field on the Anthropic path must default to False rather than # raising AttributeError (extra='allow' does not set absent attributes). from models.inference import AnthropicMessagesRequest assert AnthropicMessagesRequest.model_fields["bypass_permissions"].default is False req = AnthropicMessagesRequest(model = "x", messages = [], max_tokens = 8) assert bool(req.bypass_permissions) is False