> ## 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.

# Docker Sandbox System

> Secure command execution in isolated Docker containers with network proxy and credential injection

## 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

```text theme={null}
┌─────────────────────────────────────────────────────────────────────────────┐
│                           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:

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:

```rust theme={null}
// 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

```rust theme={null}
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:

```bash theme={null}
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

```bash theme={null}
# 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:

```bash theme={null}
/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

```bash theme={null}
# 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

```rust theme={null}
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

```rust theme={null}
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

```bash theme={null}
# 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

```bash theme={null}
# 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:

```bash theme={null}
export RUST_LOG=ironclaw::sandbox::proxy=debug
ironclaw run
```

### Resource Limit Errors

Increase limits if commands are being killed:

```bash theme={null}
export SANDOX_MEMORY_LIMIT_MB=4096
export SANDOX_TIMEOUT_SECONDS=300
```

## Advanced Topics

### Custom Network Allowlist

Add domains to the allowlist:

```bash theme={null}
# 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:

```rust theme={null}
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:

```rust theme={null}
let result = manager.execute_with_policy(
    "systemctl status",
    Path::new("/"),
    SandboxPolicy::FullAccess,
    HashMap::new(),
).await?;
```

<Warning>
  `FullAccess` policy runs commands directly on the host without any isolation. Use only for trusted operations.
</Warning>

## 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
