Skip to main content

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

PolicyFilesystemNetworkUse Case
ReadOnlyRead workspaceProxiedExplore code, fetch docs
WorkspaceWriteRead/write workspaceProxiedBuild software, run tests
FullAccessFull hostFullDirect 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:
  1. The network proxy intercepts outgoing HTTPS requests
  2. Credentials are injected by the proxy on the host
  3. 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:
  1. $DOCKER_HOST (if set)
  2. /var/run/docker.sock (Linux default, OrbStack, Podman Desktop)
  3. ~/.docker/run/docker.sock (Docker Desktop 4.13+)
  4. ~/.colima/default/docker.sock (Colima)
  5. ~/.rd/docker.sock (Rancher Desktop)
  6. $XDG_RUNTIME_DIR/docker.sock (rootless Docker)
  7. /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

  1. Initialization: Manager connects to Docker, starts network proxy
  2. Container Creation: Create ephemeral container with policy-based mounts
  3. Command Execution: Run command in container with timeout
  4. Output Collection: Collect stdout/stderr (max 64KB)
  5. 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_TOKENAuthorization: Bearer <token>
  • npm: NPM_TOKENAuthorization: Bearer <token>
  • PyPI: PYPI_TOKENAuthorization: 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

Build docs developers (and LLMs) love