Warn when CodeExecutor runs LLM-generated code without a Sandbox#1890
Open
TurtlesMaster1 wants to merge 1 commit into
Open
Warn when CodeExecutor runs LLM-generated code without a Sandbox#1890TurtlesMaster1 wants to merge 1 commit into
TurtlesMaster1 wants to merge 1 commit into
Conversation
When an Agent is constructed without an explicit `sandbox=` parameter,
`Agent.execute_code` falls through to `CodeExecutor.execute_and_return_result`,
which calls `exec(code, environment)` where `environment` is
`{'pd': pandas, 'plt': pyplot, 'np': numpy}`. Because the environment
has no `__builtins__` key, CPython silently inserts the full builtins
module, so LLM-generated code can call `__import__('os').system(...)`,
`open(...)`, `subprocess.run(...)`, and read environment variables.
The Docker sandbox extension is the supported mitigation but is opt-in
and not loud about the unsandboxed default. Users who follow the
quickstart and don't pass `sandbox=` to `Agent` are silently exposing
their host to anyone who can influence the LLM's input (a malicious
user prompt, a poisoned CSV column, a tool response).
This commit adds a one-shot `RuntimeWarning` plus a `logger.warning`
the first time `CodeExecutor.execute` runs without a sandbox in a
given process. The warning explains the risk, points to the
DockerSandbox mitigation, and offers an opt-out
(`Config(suppress_unsandboxed_warning=True)`) for users who have
considered the trade-off and want to silence the message.
No behavior change beyond the warning — exec() still runs as before
so this PR is backward compatible. A follow-up PR can propose a
restricted-builtins default for users who don't pass a sandbox.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CodeExecutor.executeruns LLM-generated Python viaexec(code, environment)whereenvironmentis the dict fromget_environment()—{"pd": pandas, "plt": matplotlib.pyplot, "np": numpy}. Because the dict has no__builtins__key, CPython silently inserts the full builtins module, so the generated code can call__import__("os").system(...),open(...),subprocess.run(...), and read environment variables.pandasai/sandbox/and thepandasai-dockerextension exist for the secure case, butsandboxis an optional parameter onAgent(sandbox: Sandbox = None) and the unsandboxed default is silent.A user who follows the quickstart and does not pass
sandbox=toAgentis exec'ing untrusted-LLM-generated code with full host privileges. This includes the indirect prompt-injection vector — a value inside a CSV column or a tool response can steer the LLM into emitting code that runs on the host.What this PR changes
Minimal, fully backward compatible:
CodeExecutorkeeps a reference to theConfigit was constructed with.CodeExecutor.executeruns in a process without a sandbox path, emit aRuntimeWarning(and alogger.warning) explaining the risk and pointing to theDockerSandboxextension.Config(suppress_unsandboxed_warning=True)for users who have considered the trade-off.Behavior of existing code paths is unchanged — the warning is purely informational.
execstill runs with the same environment.Why a warning rather than a default-deny
A default-deny (e.g. raising in
executeunless a sandbox is configured) would be safer but would break every existing quickstart-style integration. That's a maintainer call. This PR is the cheapest safety upgrade — strictly additive, no behavior change beyond a one-shot stderr warning — and leaves the door open for a future PR that defaults to a restricted-builtins environment when no sandbox is supplied.Severity
The unsandboxed default is, in practice, RCE-via-prompt-injection: any user input the LLM consumes (a prompt, a CSV cell, an API tool response) becomes a code-execution vector on the host.
Config(suppress_unsandboxed_warning=True)documents the opt-in nature of the risk;Agent(..., sandbox=DockerSandbox())is the documented secure path.Related disclosures
Cross-project pattern audit of LLM-code-execution sandboxes in AI agent frameworks. Companion PRs for related (but distinct) sandbox bugs in two other frameworks: huggingface/smolagents#2271, run-llama/llama_index#21633.
Happy to follow up with a stricter default in a separate PR if maintainers want to discuss the breaking-change trade-off.