MCP Server Sandboxing
Plugged.in implements robust sandboxing for all STDIO MCP servers to ensure security and resource isolation. This guide covers the sandboxing architecture, configuration, and best practices.
Overview
Sandboxing is enabled by default for all STDIO MCP servers. Never disable sandboxing in production environments unless absolutely necessary.
Sandboxing provides:
Process Isolation : Each MCP server runs in its own isolated environment
Filesystem Protection : Restricted access to system files and directories
Resource Limits : CPU, memory, and I/O constraints
Network Control : Optional network isolation for untrusted servers
Privilege Dropping : Servers run with minimal privileges
Sandboxing Technologies
Bubblewrap (Primary)
Bubblewrap is the preferred sandboxing technology due to its lightweight nature and user-namespace support.
Features:
User namespace isolation (no root required)
Bind mount control for selective file access
Network namespace support
Resource limits via cgroups
Minimal performance overhead
Installation:
# Ubuntu/Debian
sudo apt-get install -y bubblewrap
# RHEL/CentOS/Fedora
sudo dnf install -y bubblewrap
# Verify installation
bwrap --version
Firejail (Fallback)
Firejail provides SUID-based sandboxing with extensive security profiles.
Features:
Extensive security profiles
AppArmor/SELinux integration
X11 sandboxing support
Network filtering capabilities
Comprehensive logging
Installation:
# Ubuntu/Debian
sudo apt-get install -y firejail
# RHEL/CentOS/Fedora
sudo dnf install -y firejail
# Verify installation
firejail --version
FUSE Requirements
Some applications require FUSE (Filesystem in Userspace) support:
# Install FUSE3
sudo apt-get install -y fuse3 libfuse3-3
# Enable FUSE for containers
sudo modprobe fuse
# Verify FUSE is available
fusermount3 --version
Configuration
Environment Variables
Configure sandboxing behavior through environment variables:
# Sandboxing Type
MCP_ISOLATION_TYPE=bubblewrap # Options: bubblewrap | firejail | none
MCP_ISOLATION_FALLBACK=firejail # Fallback if primary not available
# Network Isolation
MCP_ENABLE_NETWORK_ISOLATION=false # Set to true for strict isolation
# Resource Limits
MCP_CPU_CORES_MAX=0.5 # Maximum CPU cores (0.5 = 50% of one core)
MCP_MEMORY_MAX_MB=512 # Maximum memory in MB
MCP_IO_READ_MBPS=10 # I/O read limit in MB/s
MCP_IO_WRITE_MBPS=5 # I/O write limit in MB/s
MCP_PROCESS_TIMEOUT_MS=300000 # Process timeout in milliseconds
MCP_STARTUP_TIMEOUT_MS=10000 # Startup timeout in milliseconds
# Package Storage
MCP_PACKAGE_STORE_DIR=/var/mcp-packages
MCP_PNPM_STORE_DIR=/var/mcp-packages/pnpm-store
MCP_UV_CACHE_DIR=/var/mcp-packages/uv-cache
Sandboxing Modes
Bubblewrap Mode Firejail Mode No Sandboxing Default and recommended mode // Bubblewrap configuration
{
isolation : {
type : "bubblewrap" ,
config : {
unshareAll : true , // Unshare all namespaces
shareNet : true , // Allow network (configurable)
dieWithParent : true , // Terminate on parent exit
newSession : true , // New session for process
uid : 1000 , // Run as non-root user
gid : 1000 , // Run as non-root group
hostname : "mcp-sandbox" , // Isolated hostname
capDrop : [ "ALL" ], // Drop all capabilities
capAdd : [ "CAP_NET_BIND_SERVICE" ] // Add specific capabilities
}
}
}
Implementation Details
Filesystem Isolation
The sandboxing system creates isolated filesystem views:
// Bubblewrap filesystem bindings
const filesystemBindings = [
// Read-only system directories
{ source: "/usr" , target: "/usr" , readonly: true },
{ source: "/lib" , target: "/lib" , readonly: true },
{ source: "/lib64" , target: "/lib64" , readonly: true },
// Writable workspace
{ source: "/tmp/mcp-workspace" , target: "/workspace" , readonly: false },
// Package manager directories
{ source: MCP_PACKAGE_STORE_DIR , target: MCP_PACKAGE_STORE_DIR , readonly: false },
// Optional: User home (restricted)
{ source: "~/.config" , target: "~/.config" , readonly: true }
];
Resource Limits
Resource constraints applied to sandboxed processes:
// Resource limit configuration
const resourceLimits = {
cpu: {
cores: 0.5 , // 50% of one CPU core
nice: 10 // Lower priority
},
memory: {
max: 512 * 1024 * 1024 , // 512 MB
swap: 0 // No swap usage
},
io: {
readBandwidth: 10 * 1024 * 1024 , // 10 MB/s read
writeBandwidth: 5 * 1024 * 1024 , // 5 MB/s write
maxOpenFiles: 1024 // File descriptor limit
},
process: {
maxProcesses: 32 , // Process limit
timeout: 300000 // 5 minute timeout
}
};
Network Isolation
Control network access for sandboxed servers:
Full Network Access (Default)
MCP_ENABLE_NETWORK_ISOLATION=false
Servers can access external networks
Suitable for API-based MCP servers
Docker socket access allowed
MCP_ENABLE_NETWORK_ISOLATION=true
No network access
Loopback interface only
Suitable for compute-only servers
// Advanced network configuration
{
network : {
isolation : "partial" ,
allowedHosts : [ "api.example.com" ],
allowedPorts : [ 443 , 8080 ],
denyLocal : true
}
}
Security Considerations
Privilege Escalation Prevention
Drop All Capabilities : Remove all Linux capabilities by default
No New Privileges : Prevent privilege escalation via setuid
User Namespace : Run in unprivileged user namespace
Seccomp Filtering : Restrict system calls
Directory Traversal Protection
// Path validation for sandbox
function validateSandboxPath ( path : string ) : boolean {
const normalized = path . normalize ( path );
const resolved = path . resolve ( path );
// Prevent directory traversal
if ( normalized . includes ( '..' )) return false ;
// Ensure path is within allowed directories
const allowedPaths = [
'/tmp/mcp-workspace' ,
MCP_PACKAGE_STORE_DIR
];
return allowedPaths . some ( allowed =>
resolved . startsWith ( allowed )
);
}
OAuth and Authentication
Special handling for OAuth-enabled MCP servers:
// OAuth directory isolation
if ( server . requiresOAuth ) {
const oauthDir = path . join (
MCP_PACKAGE_STORE_DIR ,
'servers' ,
server . uuid ,
'oauth'
);
// Bind OAuth directory for token storage
filesystemBindings . push ({
source: oauthDir ,
target: oauthDir ,
readonly: false
});
}
Troubleshooting
Common Issues
Error: “Permission denied: /var/mcp-packages”Solution: # Fix ownership and permissions
sudo mkdir -p /var/mcp-packages
sudo chown -R $USER : $USER /var/mcp-packages
sudo chmod -R 755 /var/mcp-packages
Error: “fusermount: fuse device not found”Solution: # Install and enable FUSE
sudo apt-get install -y fuse3
sudo modprobe fuse
# For Docker containers
docker run --cap-add SYS_ADMIN --device /dev/fuse
Network isolation too restrictive
Error: “Cannot connect to API endpoint”Solution: # Disable network isolation for API servers
export MCP_ENABLE_NETWORK_ISOLATION = false
# Or allow specific servers to bypass
server.applySandboxing = false # Use with caution
Debug Mode
Enable debug logging for sandboxing:
# Enable sandbox debugging
export DEBUG = mcp : sandbox
export MCP_SANDBOX_VERBOSE = true
# View sandbox configuration
cat /proc/[PID]/status | grep Cap
cat /proc/[PID]/cgroup
Testing Sandboxing
Verify sandboxing is working:
# Test with bubblewrap
bwrap \
--unshare-all \
--share-net \
--die-with-parent \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--tmpfs /tmp \
--proc /proc \
--dev /dev \
-- /bin/sh -c "echo 'Sandbox works!'"
# Test with firejail
firejail \
--quiet \
--private=/tmp/test \
--noroot \
--net=none \
-- /bin/sh -c "echo 'Firejail works!'"
Best Practices
Always Use Sandboxing
Never disable sandboxing in production. If a server requires it, investigate alternatives.
Principle of Least Privilege
Grant minimal permissions required for functionality.
Regular Updates
Keep sandboxing tools updated for latest security fixes.
Monitor Resource Usage
Track CPU, memory, and I/O usage to tune limits.
Test Thoroughly
Test MCP servers in sandbox before production deployment.
Document Exceptions
If sandboxing must be disabled, document the reason and compensating controls.
Sandboxing overhead is minimal:
Metric No Sandbox Bubblewrap Firejail Startup Time 100ms 120ms (+20%) 150ms (+50%) Memory Overhead 0 MB 2-4 MB 5-10 MB CPU Overhead 0% < 1% 1-2% I/O Overhead 0% < 1% 2-3%
Docker Containers
For Docker deployments:
# Install sandboxing tools in container
RUN apt-get update && apt-get install -y \
bubblewrap \
firejail \
fuse3
# Enable required capabilities
docker run \
--cap-add SYS_ADMIN \
--cap-add NET_ADMIN \
--security-opt apparmor=unconfined \
--device /dev/fuse \
pluggedin:latest
Kubernetes
For Kubernetes deployments:
securityContext :
capabilities :
add :
- SYS_ADMIN
- NET_ADMIN
privileged : false
runAsNonRoot : true
runAsUser : 1000
Support
For sandboxing assistance: