Never Grant Blanket Shell Access in Production: What to Do Instead
Blanket shell access (run_command, bash, powershell with arbitrary strings) turns your agent into remote code execution with a chat UI.
Search across all documentation pages
Blanket shell access (run_command, bash, powershell with arbitrary strings) turns your agent into remote code execution with a chat UI.
Production agents should almost never get an unrestricted shell. Prefer structured tools, allowlisted binaries, sandboxes, and human gates for anything that can mutate the world.
rm, data exfil, crypto miners, and cloud CLI abuse a matter of time - not if.A shell is a meta-tool: one interface that can invoke nearly every other program on the machine.
That is excellent for humans under supervision and terrible as a default model action space.
Production failures look like:
kubectl or cloud CLIs using the host's ambient credentialsPersonal experiments and locked-down developer laptops are a different risk tier. This page is about production: multi-user systems, shared secrets, customer data, and uptime.
"Production" includes the worker that serves real customers, the cron agent that touches prod data, and the support bot with CRM write access - not only the public website.
Any tool roughly shaped like:
run_shell(command: str, cwd?: str) -> stdout/stderrwithout a hard allowlist, path jail, network policy, and secret scrubbing.
Wrappers that still pass the string to bash -lc are still blanket shell.
create_refund, fetch_order, restart_service(service_id) implemented in code against APIs.deploy(version), tail_logs(service, minutes) with enum service names.["git", "status"]-style argv arrays, not shell strings; fixed binary paths.| Pattern | Example | Risk |
|---|---|---|
| Shell string | git status; curl evil | Metacharacters, chaining |
| Argv allowlist | ["/usr/bin/git", "status"] | Much smaller |
| API tool | git_status(repo_id) | Smallest for product surfaces |
If you must run processes, prefer subprocess with a list of arguments and shell=False, plus an allowlist of binaries and subcommands.
Commands (or file tools) may only read/write under a per-tenant work directory.
Reject .., absolute paths outside the jail, and access to ~/.ssh, cloud config, and secret mounts.
Production shells often inherit:
Those must not be available to agent-spawned processes. Use separate task roles and containers without those mounts.
Even structured tools need gates when effects are irreversible.
Shell makes gating harder because intent is opaque. deploy(version="1.2.3") is reviewable; kubectl apply -f - <<'EOF' ... is not.
Record argv, policy decision, user/run id, exit code, and truncated output.
If you cannot explain last week's shell commands to an auditor, you are not ready for shell in prod.
Developer productivity agents. Internal coding agents sometimes need tests and linters. Ship run_tests, run_linter, typecheck as fixed pipelines in CI-like sandboxes rather than free shell on prod hosts.
Migration from shell demos. Inventory every command the demo used; promote each to a named tool or allowlisted argv recipe; delete run_shell from the prod tool registry.
Multi-agent systems. Never give a "planner" the shell of an "ops" agent. Handoff a change request object, not a shared root shell.
Windows and macOS agents. PowerShell and zsh are still meta-tools. Same rules: structured actions, jails, no ambient admin.
Compliance. Regulated environments often forbid unsupervised shell on systems of record. Use this as a forcing function for better tools.
| Approach | Strength | Weakness | Best fit |
|---|---|---|---|
| No shell, API tools only | Clear authz | Less flexible | Most business agents |
| Allowlisted argv in sandbox | Some flexibility | Design + maintenance | Controlled automation |
| Containerized script runner | User code without host power | Still abuse risk | Data/code assistants |
| Supervised break-glass shell | Escape hatch | Slow, needs people | Incidents only |
| Blanket shell on prod | Demo speed | Catastrophic tail risk | Do not ship |
cat and curl still exfiltrate.Rare break-glass with human approval, dedicated sacrifice hosts, and no prod secrets - not autonomous customer-facing loops.
A run_tests tool that executes a fixed command in a CI sandbox image with the repo mount, network off or allowlisted for deps cache only.
Job runner with container, resource limits, and output size caps. Do not run them on the API node.
Still risky (secrets in files). Prefer list_files and read_file with path jail and redaction.
Ban tools that accept raw command strings; review new tools for shell=True, os.system, and eval of model text.
No. An MCP server that exposes raw shell is the same hazard. Allowlist MCP servers and tools carefully.
Disable the tool globally, rotate credentials the host could reach, audit command logs, and treat it as a security incident.
Personal risk can be accepted by a single owner; production risk is organizational. See personal shell-risk material, but do not copy laptop defaults into servers.
Only if scripts are constrained (cwd jail, no network, no secret env). Prefer running fixed entrypoints over arbitrary -c strings.
Commands denied by policy, commands with high entropy / encoding, spikes in egress, unexpected child processes, secret scanning hits in stdout.
Yes for tool shape. Staging may use softer data, but not a wider shell.
Build a small internal platform of reusable tools (deploy, logs, tickets). Agents compose tools; they should not reimplement ops via bash.
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.
Reviewed by Chris St. John·Last updated Jul 16, 2026