n layer.
This finding enables secure-by-default AI agent architectures. Developers can now run untrusted or third-party MCP servers with confidence, knowing that credential exfiltration and unauthorized outbound communication are structurally prevented.
Core Solution
Implementing OS-level sandboxing for MCP servers requires a three-phase approach: CLI installation, host configuration modification, and policy definition. The architecture relies on native operating system primitives rather than virtualization, ensuring minimal performance impact while maintaining strict enforcement boundaries.
Step 1: Install the Sandbox Runtime CLI
The enforcement layer is distributed as a global Node.js package. Installation requires no system dependencies or daemon services.
npm install -g @anthropic-ai/sandbox-runtime
Step 2: Wrap the MCP Server Command
Host configurations typically launch MCP servers via package managers. To apply sandboxing, replace the direct execution command with the srt wrapper. The original command and arguments are passed through the args array.
Before (Unrestricted):
{
"mcpServers": {
"data-pipeline": {
"command": "npx",
"args": ["-y", "@community/data-connector"]
}
}
}
After (Sandboxed):
{
"mcpServers": {
"data-pipeline": {
"command": "srt",
"args": ["npx", "-y", "@community/data-connector"]
}
}
}
Architecture Rationale: Wrapping at the command level ensures that the sandboxing layer intercepts the process before it inherits environment variables or opens file descriptors. This approach avoids modifying the MCP server's source code, maintaining compatibility with existing npm packages and preserving the original execution context while applying strict boundaries.
Step 3: Define Enforcement Policies
Policies are stored in a centralized configuration file. The runtime evaluates these rules at process startup, applying deny-then-allow semantics. Filesystem and network restrictions are configured independently to address distinct threat vectors.
{
"filesystem": {
"denyRead": ["~/.ssh", "~/.gnupg", "/etc/shadow"],
"allowWrite": ["./workspace", "./temp"],
"denyWrite": ["~/.config", "~/.local"]
},
"network": {
"allowedDomains": ["api.data-provider.io", "*.npmjs.org"],
"proxyConfig": {
"http": "http://127.0.0.1:8080",
"socks": "socks5://127.0.0.1:8081"
}
}
}
Architecture Rationale:
- Filesystem Isolation: Explicitly denying sensitive directories prevents credential theft. Allowing write access only to project-specific directories ensures that temporary files or generated artifacts don't pollute the host system.
- Network Isolation: Domain allowlists restrict outbound communication to verified endpoints. The proxy configuration routes HTTP/HTTPS traffic through an HTTP proxy and fallback TCP traffic through SOCKS5. This dual-proxy architecture ensures that non-HTTP protocols (e.g., raw TCP, WebSocket upgrades) are also subject to domain validation.
- OS-Specific Enforcement: On macOS, the runtime generates dynamic Seatbelt profiles that restrict
sandbox-exec to the defined policy. On Linux, bubblewrap creates a minimal container with network namespace isolation. Both approaches leverage kernel-level enforcement, making policy bypass impossible without root privileges.
Step 4: Programmatic Integration (Advanced)
For AI agent platforms that spawn processes dynamically, the sandboxing layer exposes a SandboxManager library. This allows programmatic policy injection without relying on static configuration files.
import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
const manager = new SandboxManager({
policyPath: './agent-policies.json',
logLevel: 'warn'
});
async function launchSecureAgent(serverCommand: string, serverArgs: string[]) {
const sandboxedProcess = await manager.spawn({
command: serverCommand,
args: serverArgs,
env: {
NODE_ENV: 'production',
// Explicitly strip sensitive variables
AWS_SECRET_ACCESS_KEY: undefined,
DATABASE_URL: undefined
}
});
sandboxedProcess.on('exit', (code) => {
console.log(`Agent terminated with code ${code}`);
});
return sandboxedProcess;
}
Architecture Rationale: Programmatic spawning enables dynamic policy evaluation based on agent role, user context, or runtime conditions. Explicitly unsetting sensitive environment variables prevents accidental leakage through process.env, which filesystem restrictions alone cannot address.
Pitfall Guide
1. Over-Permissive Domain Allowlists
Explanation: Adding wildcard patterns like * or broad TLDs (*.com) defeats network isolation. Attackers can register domains matching the pattern and establish outbound connections.
Fix: Use exact FQDNs or scoped subdomain wildcards (*.api.provider.io). Regularly audit allowed domains against actual traffic logs.
2. Environment Variable Leakage
Explanation: Filesystem and network restrictions do not hide process.env. Malicious code can read DATABASE_URL, API_KEYS, or AWS_CREDENTIALS directly from memory.
Fix: Explicitly unset or override sensitive variables in the host configuration or programmatic spawn call. Use secret management tools that inject credentials at runtime rather than storing them in environment files.
3. Ignoring OS-Specific Enforcement Differences
Explanation: macOS and Linux enforce policies differently. macOS relies on Seatbelt profiles, which may behave unexpectedly with certain GUI frameworks. Linux uses bubblewrap and network namespaces, which require cap_sys_admin in some restricted environments.
Fix: Test sandboxing policies on the target OS before deployment. On Linux, verify that the user has permission to create network namespaces. On macOS, ensure Seatbelt profiles are correctly generated by checking system logs.
4. Proxy Bypass via Raw TCP Fallback
Explanation: Developers sometimes assume HTTP proxy routing covers all traffic. Non-HTTP protocols (e.g., gRPC, raw TCP, custom binary protocols) bypass HTTP proxies if SOCKS5 fallback isn't configured.
Fix: Always configure both HTTP and SOCKS5 proxy endpoints. Verify that the SOCKS5 proxy enforces the same domain allowlists as the HTTP proxy.
5. Beta Configuration Drift
Explanation: The sandboxing runtime is marked as a beta research preview. Configuration schemas may change between minor versions, breaking existing policies.
Fix: Pin the CLI version in your package.json or deployment manifest. Implement a schema validation script that runs during CI/CD to catch breaking changes before they reach production.
6. Debugging Output Suppression
Explanation: Sandboxed processes may have stdout/stderr redirected or filtered, making it difficult to diagnose crashes or policy violations.
Fix: Enable explicit logging channels in the policy configuration. Use srt --verbose during development to capture enforcement decisions. Redirect logs to a dedicated file rather than relying on terminal output.
7. Over-Isolating Development Workflows
Explanation: Strict policies can break local development tools that rely on localhost ports, hot-reload mechanisms, or inter-process communication.
Fix: Add explicit localhost exceptions (127.0.0.1, localhost) to the network allowlist. Use environment-specific policy files (e.g., policy.dev.json, policy.prod.json) to relax restrictions during development while maintaining strict enforcement in production.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Local Development | Relaxed allowlists + localhost exceptions | Enables hot-reload, debugging, and rapid iteration | Low (minor policy tuning) |
| CI/CD Pipeline | Strict deny-then-allow + env var stripping | Prevents credential leakage during automated builds | Medium (requires policy maintenance) |
| Production Agent Host | OS-level sandboxing + proxy enforcement | Eliminates direct socket access and filesystem traversal | Low (negligible runtime overhead) |
| Multi-Tenant SaaS | Programmatic SandboxManager + dynamic policies | Isolates tenant contexts and enforces role-based access | High (requires architecture changes) |
Configuration Template
{
"filesystem": {
"denyRead": [
"~/.ssh",
"~/.gnupg",
"~/.aws",
"~/.config/gcloud",
"/etc/passwd",
"/etc/shadow"
],
"allowWrite": [
"./workspace",
"./cache",
"./logs"
],
"denyWrite": [
"~/.config",
"~/.local",
"/tmp",
"/var"
]
},
"network": {
"allowedDomains": [
"api.your-service.io",
"*.npmjs.org",
"registry.yarnpkg.com"
],
"proxyConfig": {
"http": "http://127.0.0.1:8080",
"socks": "socks5://127.0.0.1:8081"
},
"enforceAllowlist": true,
"logDroppedConnections": true
},
"runtime": {
"envStrip": [
"AWS_SECRET_ACCESS_KEY",
"DATABASE_URL",
"PRIVATE_KEY_PATH",
"SESSION_TOKEN"
],
"maxFileDescriptors": 1024,
"cpuQuota": "50%"
}
}
Quick Start Guide
- Install the runtime: Run
npm install -g @anthropic-ai/sandbox-runtime and verify installation with srt --version.
- Wrap your MCP server: Update your host configuration to use
srt as the command and pass the original execution arguments through the args array.
- Create a baseline policy: Generate
~/.srt-settings.json with denyRead: ["~/.ssh"] and an empty allowedDomains list to establish a secure-by-default posture.
- Validate enforcement: Start the MCP server and monitor traffic logs. Add domains to the allowlist only when legitimate outbound requests are blocked.
- Iterate and harden: Gradually expand filesystem write permissions and network allowlists based on actual usage patterns. Pin the CLI version and integrate policy validation into your deployment workflow.