Make the sandbox prompt match what the tools actually enforce

The terminal does not enforce a host allowlist (git and pip still reach
the network), user attachments go to the RAG store rather than the
sandbox workdir, and the code nudge named a possibly-disabled sibling
tool. Reword the sandbox note to attribute the public allowlist to the
python tool and the curl/wget block to the terminal, separate attached
documents from workdir contents, make the code tip tool-neutral, and
point the blocked-network message at the python egress for public hosts.
This commit is contained in:
danielhanchen 2026-07-19 12:54:44 +00:00
commit 04434151f9
4 changed files with 84 additions and 26 deletions

View file

@ -2955,18 +2955,21 @@ WEB_SEARCH_TOOL = {
_SANDBOX_PATHS_NOTE = (
" The working directory is an isolated scratch space that may already hold "
"files from earlier work in this conversation or project, plus anything you "
"create here or that is uploaded; it persists across this conversation and, "
"for a project, across the project's threads. Code execution can fetch from a "
"fixed allowlist of public sites (such as github.com, huggingface.co, and "
"pypi.org); shell network commands are blocked, and neither can reach the "
"user's own machines, private hosts, or arbitrary addresses. A repository, "
"folder, or file the user refers to is not present "
"here unless it was uploaded, created here, or already part of this project, "
"so list the working directory to see what is available rather than assuming "
"a mentioned path exists or guessing where it lives. Read and write files "
"using relative paths in the working directory; absolute paths like "
"/mnt/data or /tmp/outputs do not exist. If the files you need are not here, "
"ask the user to upload them or provide an exact path instead of guessing one."
"create here; it persists across this conversation and, for a project, "
"across the project's threads. It cannot see the user's own computer or the "
"files stored on it. Internet access is limited: the python tool can fetch "
"only from a fixed allowlist of public sites (such as github.com, "
"huggingface.co, and pypi.org), not the user's own machines, private hosts, "
"or arbitrary addresses, and the terminal blocks direct download commands "
"like curl and wget. Documents the user attaches to the chat are retrieved "
"separately and are not listed here. A repository, folder, or file the user "
"refers to is not present here unless you created it here or it is already "
"part of this project, so list the working directory to see what is "
"available rather than assuming a mentioned path exists or guessing where it "
"lives. Read and write files using relative paths in the working directory; "
"absolute paths like /mnt/data or /tmp/outputs do not exist. If the files "
"you need are not here, ask the user to provide them or an exact path "
"instead of guessing one."
)
PYTHON_TOOL = {
@ -5849,11 +5852,12 @@ def _bash_exec(
base = f"Blocked command(s) for safety: {', '.join(sorted(blocked))}."
if blocked & _NETWORK_BLOCKED_COMMANDS:
return (
base + " This sandbox cannot reach other machines or remote "
"hosts over the network, so files that live on another "
"machine are not accessible from here. Do not retry with "
"other remote-access commands; ask the user to upload the "
"files they want you to work with."
base + " Direct network commands are blocked in the "
"terminal. Public files on allowlisted sites (such as "
"github.com, huggingface.co, or pypi.org) can be downloaded "
"from Python code instead; the user's own machine and other "
"private or arbitrary hosts are not reachable, so for those "
"ask the user to upload the files they want you to work with."
)
return base
elif not _harden_parent_against_proc_env_leak():

View file

@ -2404,14 +2404,13 @@ _TOOL_WEB_EXPANDED_TIP = (
)
_TOOL_CODE_TIP = (
"Use code execution for math, calculations, data processing, or to parse "
"and analyze information from tool results. The python and terminal tools "
"run in a sandbox whose working directory is an isolated scratch space that "
"may already hold files from earlier work and can reach only a fixed "
"allowlist of public sites, not the user's own machines or private hosts, so "
"do not assume a file, folder, or repository the user mentions is already "
"present. List the working directory to see what is there; if what you need "
"is not present, ask the user to upload it or give an exact path rather than "
"running commands against a guessed one."
"and analyze information from tool results. It runs in a sandbox whose "
"working directory is an isolated scratch space that may already hold files "
"from earlier work; it cannot access the user's own computer, and its "
"internet access is limited, so do not assume a file, folder, or repository "
"the user mentions is already present. List the working directory to see "
"what is there; if what you need is not present, ask the user to provide it "
"or give an exact path rather than running commands against a guessed one."
)
_TOOL_ARTIFACT_TIP = (
"For HTML, CSS, or JavaScript canvas requests, call render_html once when "

View file

@ -173,6 +173,25 @@ class TestToolActionNudge:
def test_balanced_nudge_empty_without_known_tool_categories(self):
assert _build_tool_action_nudge(tools = [], model_name = "Llama-3.1-8B-Instruct") == ""
def test_code_tip_does_not_name_a_disabled_sibling_code_tool(self):
# has_code fires when either python or terminal is present, so the code tip
# must stay tool-neutral: a request that enabled only one must never name
# the other as an available tool (the missing-tool hallucination the
# render_html gate already avoids).
py_only = _build_tool_action_nudge(
tools = [{"type": "function", "function": {"name": "python"}}],
model_name = "Llama-3.1-8B-Instruct",
)
assert "Use code execution for math" in py_only
assert "terminal" not in py_only.lower()
term_only = _build_tool_action_nudge(
tools = [{"type": "function", "function": {"name": "terminal"}}],
model_name = "Llama-3.1-8B-Instruct",
)
assert "Use code execution for math" in term_only
assert "python" not in term_only.lower()
# =====================================================================
# Pydantic model tests

View file

@ -22,7 +22,12 @@ _BACKEND_DIR = str(Path(__file__).resolve().parent.parent)
if _BACKEND_DIR not in sys.path:
sys.path.insert(0, _BACKEND_DIR)
from core.inference.tools import PYTHON_TOOL, TERMINAL_TOOL, _SANDBOX_PATHS_NOTE
from core.inference.tools import (
PYTHON_TOOL,
TERMINAL_TOOL,
_SANDBOX_PATHS_NOTE,
_bash_exec,
)
def test_note_does_not_claim_full_network_isolation():
@ -48,3 +53,34 @@ def test_note_does_not_claim_project_sandbox_starts_empty():
def test_note_is_appended_to_both_tool_descriptions():
assert PYTHON_TOOL["function"]["description"].endswith(_SANDBOX_PATHS_NOTE)
assert TERMINAL_TOOL["function"]["description"].endswith(_SANDBOX_PATHS_NOTE)
def test_note_scopes_network_block_to_the_terminal_not_all_shell_commands():
# The terminal leaves the network namespace intact and does not block git/pip,
# so the note must not claim shell network is fully blocked; it names the
# commands that are blocked (curl / wget) and attributes the host allowlist to
# the python tool.
lowered = _SANDBOX_PATHS_NOTE.lower()
assert "shell network commands are blocked" not in lowered
assert "curl" in lowered and "wget" in lowered
assert "python tool can fetch" in lowered
def test_note_distinguishes_attachments_from_sandbox_uploads():
# Chat/project document uploads land in the RAG store, not the sandbox workdir,
# so the note must not tell the model that uploaded files appear via `ls`.
lowered = _SANDBOX_PATHS_NOTE.lower()
assert "was uploaded" not in lowered
assert "or that is uploaded" not in lowered
assert "retrieved separately" in lowered
assert "attach" in lowered
def test_blocked_network_command_message_points_to_python_egress():
# A blocked curl/wget must not tell the model the whole sandbox is offline: the
# python tool can still fetch allowlisted public hosts.
msg = _bash_exec("curl https://raw.githubusercontent.com/foo/bar/main/x.py").lower()
assert "blocked command" in msg
assert "cannot reach other machines or remote hosts" not in msg
assert "python" in msg
assert "github.com" in msg