Dev ToolsΒ·
advanced
Β·14 min readΒ·Jul 9, 2026

Designing Secure Execution Sandboxes for Bash & Shell Tool Calls

Learn how to build secure sandboxes using Docker containers and system boundaries to run terminal commands safely via MCP.

sandboxsecuritybashDockerexecution
Interactive Tool
1-Click Export

Generate & Validate Multi-Client MCP Config

One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.

Open in Generator

Secure Execution Sandboxes for Bash & Shell Tool Calls

Giving an LLM agent access to run shell commands (/bin/bash or cmd.exe) directly on your host machine is a critical security vulnerability. An agent could accidentally rm -rf important directories, leak environment variables, or download malicious software via arbitrary curl commands.

Prerequisites

  1. β–ΈDocker Desktop or the Docker Engine installed and running on your host machine.
  2. β–ΈNode.js installed to wrap the Docker execution in an MCP server.

Architecture of a Sandboxed MCP Execution Server

To run bash scripts safely, execute the commands within an isolated Docker container configured with CPU constraints, strict memory limits, and no host network bridge:

code
[MCP Client] --> [Bash MCP Server] --> [Spawns Ephemeral Docker Container]
                                              |
                                              +---> CPU Limit: 0.5 Cores
                                              +---> Memory Limit: 512MB
                                              +---> Read-Only Host Mounts
                                              +---> No Internet Bridge

Node.js Docker-based Shell Execution Script

Here is an example TypeScript implementation of a tool that accepts an agent's shell command and safely executes it inside an Alpine Linux sandbox:

typescript
import { exec } from 'child_process';
import util from 'util';
const execPromise = util.promisify(exec);

async function runCommandInSandbox(userCommand: string): Promise<string> {
  // Deep sanitization is still necessary to prevent command injection into the Docker CLI itself
  const sanitized = userCommand.replace(/'/g, "'\\''");
  
  const dockerCmd = `docker run --rm \
    --network none \
    --memory 512m \
    --cpus 0.5 \
    alpine:latest sh -c '${sanitized}'`;

  try {
    const { stdout, stderr } = await execPromise(dockerCmd, { timeout: 10000 });
    return stdout || stderr;
  } catch (err: any) {
    return `Execution Error: ${err.message}`;
  }
}

Best Practices

  • β–ΈDrop Network Access: By using --network none, you guarantee the agent cannot curl or wget external scripts, blocking potential data exfiltration or malware downloads.
  • β–ΈEphemeral Containers: The --rm flag ensures the container is immediately destroyed after the command finishes. State should not persist between tool calls.
  • β–ΈHard Timeouts: Enforce a strict timeout (e.g., 10 seconds) so the agent cannot write an infinite while true loop that hogs host resources.

Troubleshooting

  • β–Έdocker: command not found: Ensure the Docker daemon is running and the docker CLI is in the PATH of the environment executing the MCP server.
  • β–ΈFiles Not Found: Since the execution happens in an isolated Alpine container, it has no access to your host filesystem. If you want the agent to read local files, you must explicitly bind-mount them using -v /path/to/host:/app:ro (read-only!).

Using with OpenAI Codex

You can use this MCP server with the OpenAI Codex CLI by adding it to your configuration:

bash
codex mcp add --name shell --command "npx -y @modelcontextprotocol/server-shell"

Note: Review the sandbox configuration carefully before granting shell access.

For a full list of recommended servers, see Best MCP Servers for OpenAI Codex.

Ready to Deploy?

Build your full agent toolstack in the Visual Generator

Combine Designing Secure Execution Sandboxes for Bash & Shell Tool Calls with databases, search APIs, and memory graphs in a single configuration file.

Customize in Generator

Related Guides