Skip to content

Docker Sandbox

The Docker sandbox provides secure, isolated execution for untrusted code. It is used when agents.sandbox.mode is set to non-main or all in openmotoko.json.

The sandbox image is minimal:

FROM node:24-alpine
RUN adduser -D -u 1001 sandbox && \
mkdir -p /workspace && \
chown sandbox:sandbox /workspace
USER sandbox
WORKDIR /workspace
ENV NODE_ENV=production

The sandbox runs as a non-root user (sandbox, UID 1001) with no elevated privileges.

ResourceLimitDescription
Memory256 MBHard memory cap
CPU50% of one corecpuQuota: 50000 (50% of 100000)
PIDs256Prevents fork bombs
Open files1024 (soft) / 2048 (hard)nofile ulimit
Processes128 (soft) / 256 (hard)nproc ulimit
Timeout30 secondsConfigurable per execution

The root filesystem is mounted read-only (ReadonlyRootfs: true). Only /workspace is writable via a tmpfs mount:

tmpfs /workspace size=64m,noexec,nosuid

The workspace is limited to 64 MB and blocks executable files (noexec) and setuid binaries (nosuid).

All Linux capabilities are dropped (CapDrop: ALL). The container cannot:

  • Change file ownership
  • Bind to privileged ports
  • Load kernel modules
  • Modify network settings
  • Access raw sockets

SecurityOpt: no-new-privileges prevents gaining additional privileges via setuid binaries or other mechanisms.

Containers are automatically removed after execution (AutoRemove: true), leaving no state behind.

PolicyBehavior
noneNo network access at all
restrictedDNS and HTTPS only (ports 53, 443)
fullUnrestricted network

Configure in openmotoko.json:

{
"agents": {
"sandbox": {
"mode": "all",
"networkPolicy": "restricted"
}
}
}
ModeDescription
offNo sandboxing (default)
non-mainSandbox sub-agents only; primary agent runs natively
allSandbox all code execution

The SandboxManager wraps DockerSandbox and reads config from openmotoko.json. It provides a execute(options) interface:

interface SandboxOptions {
image: string
command: string[]
env?: Record<string, string>
workDir?: string
networkPolicy?: 'none' | 'restricted' | 'full'
timeout?: number
memoryLimit?: number
cpuQuota?: number
}
interface SandboxResult {
stdout: string
stderr: string
exitCode: number
timedOut: boolean
}

Docker must be installed and running. The sandbox image is built automatically on first use:

Terminal window
docker build -t openmotoko/sandbox:latest -f docker/Dockerfile.sandbox .