Container Isolation
Each execution runs inside a Docker container with the following security constraints:| Control | Default | Configurable |
|---|---|---|
| Read-only root filesystem | Enabled | --writable / readonlyRootFs: false |
| No network access | none | --net host|filtered / network |
| Memory limit | 512 MB | --memory / memoryLimit |
| CPU limit | 1 core | --cpu / cpuLimit |
| PID limit | 64 | --pids-limit / pidsLimit |
| Sandbox tmpfs | 512 MB | --sandbox-size / sandboxSize |
| Tmp tmpfs | 256 MB | --tmp-size / tmpSize |
no-new-privileges | Enabled | Not configurable |
Non-root user (sandbox) | Enabled | Not configurable |
| Execution timeout | 30 seconds | --timeout / timeoutMs |
Container Filesystem
Containers use two tmpfs mounts for security and performance:/sandbox (default: 512 MB)
- Purpose: Working directory for code execution
- Mount flags:
rw,exec,nosuid,nodev - Contents:
- User code files
- Package installations (
.local,.npm-global,.bun-global) - User-created files and outputs
- Execution: Allowed (required for native extensions like numpy’s
.sofiles) - Configurable via:
--sandbox-sizeCLI flag orsandboxSizeconfig option
/tmp (default: 256 MB)
- Purpose: Temporary files and caches
- Mount flags:
rw,noexec,nosuid,nodev - Contents:
- Temporary files created by programs
- Package manager caches during installation
- Execution: Disabled (
noexecflag) for security - Configurable via:
--tmp-sizeCLI flag ortmpSizeconfig option
Packages installed with
--install are stored in /sandbox (not /tmp) because they often contain shared libraries (.so files) that need to be executable. The /tmp mount has the noexec flag which would prevent these libraries from loading.Network Control
none (Default)
The container has no network access. No DNS, no HTTP, no TCP — nothing leaves the container.
host
Full host network access. Use only when you trust the code or need unrestricted connectivity.
filtered
Bridge network with an HTTP/HTTPS proxy (proxy.mjs) that filters requests by hostname:
- Whitelist — Only matching hostnames are allowed (regex patterns)
- Blacklist — Matching hostnames are blocked (regex patterns)
HTTP_PROXY/HTTPS_PROXY environment variables. The container can only reach external hosts through the proxy.
Secret Masking
Secrets passed via--secret KEY=VALUE (CLI) or secrets: { KEY: "VALUE" } (library) are:
- Injected into the container as environment variables
- Automatically masked in all output (stdout and stderr)
***.
Output Truncation
Output is truncated tomaxOutputSize (default 1 MB) to prevent memory exhaustion from programs that produce excessive output. When truncation occurs, ExecutionResult.truncated is set to true.
Timeout Enforcement
When a timeout is reached:- The process inside the container is killed (via
timeoutshell wrapper) "EXECUTION TIMED OUT"is appended to stderr- The container is cleaned up (ephemeral) or preserved minus the killed process (persistent)
Docker Image Security
Base images are built from a multi-stage Dockerfile with:- Alpine Linux base (minimal attack surface)
- Non-root
sandboxuser - Only the runtime binary and essential dependencies
- Proxy script for filtered networking
isol8 setup --python numpy) extend the base image with additional packages but maintain the same security posture.
Best Practices
Use network: none by default
Only enable network access when the code genuinely needs it. Most code execution tasks don’t require network.
Use filtered mode with tight allowlists
When network is needed, prefer
filtered with explicit --allow patterns rather than host mode.Set appropriate resource limits
Lower memory, CPU, and PID limits to the minimum your workload needs.
Use secrets for credentials
Never embed API keys in code strings. Use
--secret to inject them as masked env vars.Use ephemeral mode
Prefer ephemeral execution for one-off tasks. Persistent mode should only be used when state preservation is genuinely needed.