> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/QwenLM/qwen-code/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox Execution

> Isolate Qwen Code execution using Docker, Podman, or macOS Seatbelt

# Sandbox Execution

Qwen Code supports sandboxed execution environments to isolate command execution and enhance security. This is particularly useful when running untrusted code or working in sensitive environments.

## Supported Sandbox Runtimes

Qwen Code supports three sandbox backends:

### Docker

Container-based isolation using Docker Engine.

### Podman

Rootless container runtime, ideal for environments without Docker daemon privileges.

### macOS Seatbelt (sandbox-exec)

Native macOS sandboxing without containers. Only available on macOS.

## Configuration

### Environment Variables

#### Enable Sandbox

```bash theme={null}
# Auto-detect available runtime (seatbelt on macOS, manual on Linux)
export QWEN_SANDBOX=true

# Specify runtime explicitly
export QWEN_SANDBOX=docker
export QWEN_SANDBOX=podman
export QWEN_SANDBOX=sandbox-exec  # macOS only
```

#### Custom Sandbox Image

```bash theme={null}
# Use a custom Docker/Podman image
export QWEN_SANDBOX_IMAGE=my-custom-image:latest
```

#### Additional Configuration

```bash theme={null}
# Pass custom flags to Docker/Podman
export SANDBOX_FLAGS="--cpus=2 --memory=4g"

# Mount additional paths (comma-separated)
export SANDBOX_MOUNTS="/path/on/host:/path/in/container:ro,/another/path:/mnt/data:rw"

# Pass environment variables to sandbox
export SANDBOX_ENV="API_KEY=secret,DEBUG=true"

# Expose ports from sandbox to host
export SANDBOX_PORTS="3000,8080"

# Control UID/GID mapping (Linux only)
export SANDBOX_SET_UID_GID=true  # Default on Linux
export SANDBOX_SET_UID_GID=false # Use image default user
```

### Command Line Options

```bash theme={null}
# Enable sandbox with auto-detection
qwen --sandbox

# Specify runtime
qwen --sandbox=docker
qwen --sandbox=podman

# Custom image
qwen --sandbox-image=myorg/qwen-sandbox:v1
```

### Settings File Configuration

In `.qwen/settings.json`:

```json theme={null}
{
  "tools": {
    "sandbox": "docker"
  }
}
```

## Docker/Podman Sandbox Details

### How It Works

When using Docker or Podman:

1. **Container Creation**: Qwen Code spawns a container with:
   * Current working directory mounted
   * User settings directory (`~/.qwen`) mounted
   * Temporary directory mounted
   * Network access configured

2. **Environment Inheritance**: The following are passed through:
   * API keys (GEMINI\_API\_KEY, OPENAI\_API\_KEY, etc.)
   * Terminal settings (TERM, COLORTERM)
   * Virtual environment paths (VIRTUAL\_ENV)
   * Google Cloud credentials

3. **Lifecycle**: Container is automatically removed on exit (`--rm` flag)

### Volume Mounts

By default, these are mounted:

```bash theme={null}
# Working directory
/path/to/project -> /path/to/project (inside container)

# User settings
~/.qwen -> /home/node/.qwen

# Temporary directory
/tmp -> /tmp

# Google Cloud config (if exists)
~/.config/gcloud -> ~/.config/gcloud:ro
```

### UID/GID Handling

On Linux, Qwen Code automatically matches the host user's UID/GID to prevent permission issues:

```typescript theme={null}
// From packages/cli/src/utils/sandbox.ts:68
async function shouldUseCurrentUserInSandbox(): Promise<boolean> {
  const envVar = process.env['SANDBOX_SET_UID_GID']?.toLowerCase().trim();
  
  if (envVar === '1' || envVar === 'true') return true;
  if (envVar === '0' || envVar === 'false') return false;
  
  // Default: true on Linux, false elsewhere
  if (os.platform() === 'linux') return true;
  return false;
}
```

This creates a user inside the container with matching UID/GID:

```bash theme={null}
# Inside container setup
groupadd -f -g ${gid} qwen
useradd -o -u ${uid} -g ${gid} -d ${homeDir} -s /bin/bash qwen
su -p qwen -c '<command>'
```

## macOS Seatbelt Sandbox

### Built-in Profiles

Qwen Code includes six built-in seatbelt profiles:

```bash theme={null}
export SEATBELT_PROFILE=permissive-open      # Default
export SEATBELT_PROFILE=permissive-closed
export SEATBELT_PROFILE=permissive-proxied
export SEATBELT_PROFILE=restrictive-open
export SEATBELT_PROFILE=restrictive-closed
export SEATBELT_PROFILE=restrictive-proxied
```

### Profile Locations

* Built-in: `packages/cli/src/utils/sandbox-macos-{profile}.sb`
* Custom: `.qwen/sandbox-macos-{profile}.sb` (project-specific)

### Custom Profile Example

Create `.qwen/sandbox-macos-custom.sb`:

```scheme theme={null}
(version 1)
(deny default)

; Allow reading from project directory
(allow file-read* (subpath (param "TARGET_DIR")))

; Allow writing to temp directory
(allow file-write* (subpath (param "TMP_DIR")))

; Allow network access
(allow network*)

; Allow process execution
(allow process-exec)
```

Then use it:

```bash theme={null}
export SEATBELT_PROFILE=custom
qwen
```

### Seatbelt Variables

Available in `.sb` files:

* `TARGET_DIR`: Current working directory
* `TMP_DIR`: System temporary directory
* `HOME_DIR`: User home directory
* `CACHE_DIR`: macOS cache directory
* `INCLUDE_DIR_0` through `INCLUDE_DIR_4`: Additional workspace directories

## Proxy Support

For sandboxed environments with restricted network access:

### Container-Based Proxy

```bash theme={null}
# Proxy command runs in separate container with network access
export QWEN_SANDBOX_PROXY_COMMAND="mitmproxy --mode transparent"
export HTTPS_PROXY=http://localhost:8877

qwen --sandbox
```

The proxy container:

* Runs on port 8877 by default
* Connected to both host network and internal sandbox network
* Automatically started/stopped with sandbox

### macOS Seatbelt Proxy

```bash theme={null}
export QWEN_SANDBOX_PROXY_COMMAND="mitmproxy --mode transparent"
export HTTPS_PROXY=http://localhost:8877
export SEATBELT_PROFILE=permissive-proxied

qwen
```

## Custom Sandbox Images

### Building Custom Image

Create `.qwen/sandbox.Dockerfile`:

```dockerfile theme={null}
FROM node:20-bookworm

# Install additional tools
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Install Python packages
RUN pip3 install --no-cache-dir requests numpy pandas

# Set working directory
WORKDIR /workspace

# Copy entrypoint if needed
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
```

### Build and Use

```bash theme={null}
# Build the image
export BUILD_SANDBOX=1
qwen --sandbox

# Or build manually
docker build -t my-qwen-sandbox -f .qwen/sandbox.Dockerfile .

# Use custom image
export QWEN_SANDBOX_IMAGE=my-qwen-sandbox
qwen --sandbox
```

## Startup Scripts

### Container Bashrc

Create `.qwen/sandbox.bashrc` to customize the container environment:

```bash theme={null}
# .qwen/sandbox.bashrc
# This file is sourced inside the sandbox container

# Set up Python virtual environment
if [ -d "venv" ]; then
    source venv/bin/activate
fi

# Add project bin to PATH
export PATH="$PWD/bin:$PATH"

# Set up Node.js version
if command -v nvm &> /dev/null; then
    nvm use
fi

# Custom aliases
alias ll='ls -la'
alias gs='git status'
```

This file is automatically sourced on container startup.

## Troubleshooting

### Permission Issues (Linux)

**Problem**: Files created in sandbox have wrong ownership.

**Solution**: Enable UID/GID matching:

```bash theme={null}
export SANDBOX_SET_UID_GID=true
qwen --sandbox
```

### Image Not Found

**Problem**: `Sandbox image 'qwen-code-sandbox' is missing`

**Solution**: Build the sandbox image:

```bash theme={null}
# For linked development builds
export BUILD_SANDBOX=1
qwen --sandbox

# Or pull from registry (if available)
docker pull qwen-code-sandbox:latest
```

### Network Access Issues

**Problem**: Container cannot access network.

**Solution**: Check Docker/Podman network configuration:

```bash theme={null}
# Test network access
qwen --sandbox -- curl -I https://google.com

# Check network mode
docker inspect <container-name> | grep NetworkMode
```

### Virtual Environment Issues

**Problem**: Python venv not working in sandbox.

**Solution**: The sandbox creates a separate venv directory:

```bash theme={null}
# In .qwen/sandbox.bashrc
if [ ! -d ".qwen/sandbox.venv/bin" ]; then
    python3 -m venv .qwen/sandbox.venv
fi
source .qwen/sandbox.venv/bin/activate
```

### Port Binding Issues

**Problem**: Cannot access exposed ports.

**Solution**: Ensure ports are properly exposed:

```bash theme={null}
# Expose ports
export SANDBOX_PORTS="3000,8080"

# Verify port mapping
docker ps
# Should show: 0.0.0.0:3000->3000/tcp
```

### macOS Seatbelt Issues

**Problem**: Seatbelt denies file access.

**Solution**: Use a more permissive profile or create custom profile:

```bash theme={null}
# Use permissive profile
export SEATBELT_PROFILE=permissive-open

# Check sandbox logs
log stream --predicate 'process == "sandbox-exec"'
```

## Security Considerations

### Container Isolation

* Containers run with `--init` flag for proper signal handling
* Containers auto-removed on exit (`--rm`)
* Host Docker socket NOT mounted by default
* Network can be restricted using internal networks + proxy

### Seatbelt Isolation

* File system access restricted to defined paths
* Network access can be blocked in restrictive profiles
* Process execution can be limited

### Best Practices

1. **Use restrictive profiles** in production
2. **Mount only necessary paths** with appropriate permissions (ro/rw)
3. **Review custom Dockerfiles** before building
4. **Use proxy mode** for network filtering
5. **Keep sandbox images updated** with security patches

## Integration Tests

For testing with sandbox enabled:

```bash theme={null}
export QWEN_CODE_INTEGRATION_TEST=true
export QWEN_SANDBOX=docker

qwen --test
```

Integration test mode:

* Uses unique container names with random suffixes
* Supports checkpoint/resume functionality
* Handles temporary file cleanup

## Advanced Topics

### Multiple Workspaces

Mount additional workspace directories:

```bash theme={null}
export SANDBOX_MOUNTS="/workspace1:/ws1:ro,/workspace2:/ws2:rw"
```

### Custom Entrypoint

Override container entrypoint:

```bash theme={null}
export SANDBOX_FLAGS="--entrypoint /custom-entrypoint.sh"
```

### Resource Limits

```bash theme={null}
export SANDBOX_FLAGS="--cpus=2 --memory=4g --memory-swap=8g"
```

### Debug Mode

Enable debugging:

```bash theme={null}
export DEBUG=true
export DEBUG_PORT=9229

qwen --sandbox
# Debugger listening on 0.0.0.0:9229
```

## Source Code References

* Sandbox implementation: `packages/cli/src/utils/sandbox.ts`
* Sandbox config: `packages/cli/src/config/sandboxConfig.ts`
* Seatbelt profiles: `packages/cli/src/utils/sandbox-macos-*.sb`
