Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nearai/ironclaw/llms.txt
Use this file to discover all available pages before exploring further.
Overview
IronClaw’s Docker sandbox system provides complete isolation for executing untrusted commands. All tool executions run in ephemeral Docker containers with strict resource limits, network controls, and security constraints.
Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ Sandbox System │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ SandboxManager │ │
│ │ │ │
│ │ • Coordinates container creation and execution │ │
│ │ • Manages proxy lifecycle │ │
│ │ • Enforces resource limits │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Container │ │ Network Proxy │ │
│ │ Runner │ │ │ │
│ │ │ │ • Allowlist │ │
│ │ • Create │◀────────▶│ • Credentials │ │
│ │ • Execute │ │ • Logging │ │
│ │ • Cleanup │ │ │ │
│ └──────────────────┘ └───────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌───────────────────┐ │
│ │ Docker │ │ Internet │ │
│ │ │ │ (allowed hosts) │ │
│ └──────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Sandbox Policies
| Policy | Filesystem | Network | Use Case |
|---|
ReadOnly | Read workspace | Proxied | Explore code, fetch docs |
WorkspaceWrite | Read/write workspace | Proxied | Build software, run tests |
FullAccess | Full host | Full | Direct execution (no sandbox) |
Policy Selection
IronClaw automatically selects the appropriate policy based on the tool being executed:
- Bash tool:
WorkspaceWrite for commands that modify files
- Read tool:
ReadOnly for read-only operations
- Write/Edit tools:
WorkspaceWrite when modifying files
Security Properties
No Credentials in Containers
Environment variables containing API keys and secrets never enter containers. Instead:
- The network proxy intercepts outgoing HTTPS requests
- Credentials are injected by the proxy on the host
- Containers only see
http_proxy and https_proxy environment variables
Network Isolation
All network traffic routes through a validating HTTP proxy:
// Default allowlist (can be extended via config)
vec![
"github.com",
"api.github.com",
"gitlab.com",
"bitbucket.org",
"npmjs.com",
"registry.npmjs.org",
"pypi.org",
"files.pythonhosted.org",
"crates.io",
"static.crates.io",
// ... see src/sandbox/config.rs for full list
]
Requests to non-allowlisted domains are blocked at the proxy level.
Container Security
- Non-root execution: Containers run as UID 1000
- Read-only root: Container filesystem is read-only (except workspace mount)
- Capability dropping: All Linux capabilities dropped, only essential ones added back
- Auto-cleanup: Containers are removed after execution (
--rm + explicit cleanup)
- Timeout enforcement: Commands are killed after the timeout (default: 120s)
Resource Limits
pub struct ResourceLimits {
pub memory_bytes: u64, // Default: 2GB
pub cpu_shares: u32, // Default: 1024
pub timeout: Duration, // Default: 120s
pub max_output_bytes: usize, // Default: 64KB
}
Container Configuration
Environment Variables
Containers receive:
http_proxy=http://172.17.0.1:PORT # Linux
http_proxy=http://host.docker.internal:PORT # macOS/Windows
https_proxy=http://172.17.0.1:PORT
No API keys or secrets are passed directly.
Volume Mounts
# ReadOnly policy
/host/workspace:/workspace:ro
# WorkspaceWrite policy
/host/workspace:/workspace:rw
# FullAccess policy
/host/workspace:/workspace:rw
/tmp:/tmp:rw
Tmpfs Mounts
Ephemeral storage for build artifacts:
/tmp:size=512M
/home/sandbox/.cargo/registry:size=1G
Docker Connection
IronClaw tries these socket locations in order:
$DOCKER_HOST (if set)
/var/run/docker.sock (Linux default, OrbStack, Podman Desktop)
~/.docker/run/docker.sock (Docker Desktop 4.13+)
~/.colima/default/docker.sock (Colima)
~/.rd/docker.sock (Rancher Desktop)
$XDG_RUNTIME_DIR/docker.sock (rootless Docker)
/run/user/$UID/docker.sock (rootless fallback)
Configuration
Environment Variables
# Enable/disable sandbox
SANDOX_ENABLED=true # default: true
# Default policy
SANDOX_POLICY=workspace_write # Options: read_only, workspace_write, full_access
# Docker image
SANDOX_IMAGE=debian:bookworm-slim # default
# Resource limits
SANDOX_MEMORY_LIMIT_MB=2048 # default: 2048
SANDOX_CPU_SHARES=1024 # default: 1024
SANDOX_TIMEOUT_SECONDS=120 # default: 120
# Network allowlist (comma-separated)
SANDOX_NETWORK_ALLOWLIST=github.com,npmjs.com,pypi.org
# Auto-pull image if missing
SANDOX_AUTO_PULL=true # default: true
Programmatic Configuration
use ironclaw::sandbox::{SandboxManagerBuilder, SandboxPolicy};
use std::time::Duration;
let manager = SandboxManagerBuilder::new()
.enabled(true)
.policy(SandboxPolicy::WorkspaceWrite)
.timeout(Duration::from_secs(60))
.memory_limit_mb(1024)
.image("debian:bookworm-slim")
.allow_domains(vec!["example.com".to_string()])
.build();
manager.initialize().await?;
Execution Flow
- Initialization: Manager connects to Docker, starts network proxy
- Container Creation: Create ephemeral container with policy-based mounts
- Command Execution: Run command in container with timeout
- Output Collection: Collect stdout/stderr (max 64KB)
- Cleanup: Remove container, return results
Example Execution
use std::collections::HashMap;
use std::path::Path;
let result = manager.execute(
"cargo build --release",
Path::new("/workspace/my-project"),
HashMap::new(),
).await?;
println!("Exit code: {}", result.exit_code);
println!("Output: {}", result.output);
println!("Duration: {:?}", result.duration);
Troubleshooting
Docker Not Available
# Check Docker is running
docker ps
# Check socket permissions
ls -l ~/.docker/run/docker.sock
# For rootless Docker, ensure socket is in expected location
echo $DOCKER_HOST
Image Pull Failures
# Manually pull the image
docker pull debian:bookworm-slim
# Or disable auto-pull and ensure image exists
export SANDOX_AUTO_PULL=false
Network Proxy Issues
Check proxy logs:
export RUST_LOG=ironclaw::sandbox::proxy=debug
ironclaw run
Resource Limit Errors
Increase limits if commands are being killed:
export SANDOX_MEMORY_LIMIT_MB=4096
export SANDOX_TIMEOUT_SECONDS=300
Advanced Topics
Custom Network Allowlist
Add domains to the allowlist:
# Via environment
export SANDOX_NETWORK_ALLOWLIST=github.com,npmjs.com,mycompany.com
# Via config
[sandbox]
network_allowlist = ["github.com", "npmjs.com", "mycompany.com"]
Credential Injection
The network proxy automatically injects credentials for allowed domains:
pub struct CredentialMapping {
pub host_pattern: String, // e.g., "api.github.com"
pub header_name: String, // e.g., "Authorization"
pub env_var_name: String, // e.g., "GITHUB_TOKEN"
pub value_template: String, // e.g., "Bearer {}"
}
Default mappings:
- GitHub:
GITHUB_TOKEN → Authorization: Bearer <token>
- npm:
NPM_TOKEN → Authorization: Bearer <token>
- PyPI:
PYPI_TOKEN → Authorization: Bearer <token>
Bypassing the Sandbox
For trusted operations, use FullAccess policy:
let result = manager.execute_with_policy(
"systemctl status",
Path::new("/"),
SandboxPolicy::FullAccess,
HashMap::new(),
).await?;
FullAccess policy runs commands directly on the host without any isolation. Use only for trusted operations.
Source Code
Key files:
src/sandbox/mod.rs - Module overview and exports
src/sandbox/manager.rs - Sandbox manager lifecycle
src/sandbox/container.rs - Docker container creation and execution
src/sandbox/config.rs - Configuration and resource limits
src/sandbox/proxy/mod.rs - Network proxy implementation