Skip to main content
isol8 treats security as a layered system, not a single toggle. Container, process, filesystem, network, and output controls are combined for untrusted code execution.

Default security baseline

Out of the box, executions run with:
  • non-root process user (sandbox, uid 100)
  • read-only root filesystem (readonlyRootFs: true)
  • writable tmpfs only at /sandbox and /tmp
  • network disabled (network: "none")
  • resource limits (timeout, CPU, memory, PID count)
  • secret masking on stdout/stderr when secrets are configured

Where to set security values

ControlCLIConfig fileAPI (/execute)Library
Network mode--netdefaults.networkoptions.networknew DockerIsol8({ network })
Filter allow rules--allownetwork.whitelistoptions.networkFilter.whitelistnetworkFilter.whitelist
Filter deny rules--denynetwork.blacklistoptions.networkFilter.blacklistnetworkFilter.blacklist
Seccomp mode/profilenot via run flagsecurity.seccomp, security.customProfilePathoptions.security.*security.*
PID limit--pids-limitno default keyoptions.pidsLimitpidsLimit
Root FS writabilityNo run overrideno default keyoptions.readonlyRootFsreadonlyRootFs
Secrets masking source--secret KEY=VALUEno default keyoptions.secretssecrets
The server merges config defaults with per-request options. Request-level options win for that execution.

Network modes

ModeBehaviorUse for
noneoutbound network blockedsafest default for untrusted code
filteredoutbound routed through in-container proxy + policy rulescontrolled external API access
hostunrestricted host networktrusted workloads only
network: "host" removes the isolation benefits of blocked/filtered egress. Avoid it for untrusted code.

Setting filtered mode policy

isol8 run script.py \
  --net filtered \
  --allow "^api\\.openai\\.com$" \
  --deny "^169\\.254\\."

How filtered enforcement works

For pooled containers in filtered mode, cleanup flushes container OUTPUT iptables rules before reuse.

Seccomp modes

Available values for security.seccomp:
  • strict (default)
  • unconfined
  • custom (requires security.customProfilePath)
{
  "security": {
    "seccomp": "custom",
    "customProfilePath": "./seccomp-profile.json"
  }
}
unconfined disables seccomp syscall filtering.
In strict mode, isol8 applies the built-in seccomp profile. Standalone server binaries include an embedded fallback copy so strict mode remains available even when profile files are not present on disk. If strict/custom profile loading fails, execution fails rather than running without seccomp.

Filesystem and process guards

  • /sandbox is writable and executable (required for native extensions and installed packages)
  • /tmp is writable but mounted noexec
  • pidsLimit constrains process fan-out
  • readonlyRootFs keeps root filesystem immutable unless explicitly disabled
isol8 run script.py \
  --pids-limit 64 \
  --sandbox-size 512m \
  --tmp-size 256m

Secret masking behavior

Secrets are injected as environment variables and then masked from stdout/stderr by value matching.
isol8 run -e "print('token=abc123')" \
  --runtime python \
  --secret API_TOKEN=abc123
Secret masking applies to stdout/stderr text. Retrieved file contents are not automatically redacted.

FAQ

No. You can use either. If both are provided, blacklist matches are denied even when whitelist would allow.
Not in the current CLI run flags. Use isol8.config.json, API options.security, or library options.
Native extensions and runtime package installs need executable paths. isol8 uses /sandbox for that and keeps /tmp non-executable to reduce abuse surface.

Troubleshooting

  • Filtered mode blocks expected domains: test your regex patterns; remember they are hostname checks and blacklist wins.
  • Unexpected open egress: verify network is not host in config defaults or request options.
  • Seccomp custom profile errors: ensure customProfilePath exists and contains valid seccomp JSON.
  • Secret still appears in downloaded artifacts: add explicit redaction before writing files you later retrieve.