A sandboxed code execution engine.
Codize Sandbox is a code execution engine that runs arbitrary code safely inside Linux namespace jails (google/nsjail). It exposes an HTTP API to receive code, execute it in an isolated environment, and return the output.
| Runtime | Identifier |
|---|---|
| Node.js | node |
| Ruby | ruby |
| Go | go |
| Bash | bash |
The container must run in privileged mode (required for nsjail to create Linux namespaces) with --cgroupns=host (required for nsjail to manage cgroups for resource limiting).
$ docker run \
--privileged \
--cgroupns=host \
-p 8080:8080 \
ghcr.io/codize-dev/sandbox:latest serveBehavior can be customized via CLI flags (see CLI Flags for the full list):
$ docker run \
--privileged \
--cgroupns=host \
-p 8080:8080 \
ghcr.io/codize-dev/sandbox:latest serve --run-timeout 10 --compile-timeout 10Create a compose.yml:
services:
sandbox:
image: ghcr.io/codize-dev/sandbox:latest
privileged: true
cgroup: host
command: ["serve", "--run-timeout", "10", "--compile-timeout", "10"]
ports:
- "8080:8080"$ docker compose up| Flag | Default | Description |
|---|---|---|
--port |
8080 (overridden by PORT env var) |
Listen port |
--run-timeout |
30 |
Run timeout in seconds |
--compile-timeout |
30 |
Compile timeout in seconds |
--output-limit |
1048576 (1 MiB) |
Maximum combined output bytes |
--max-files |
10 |
Maximum number of files per request |
--max-file-size |
262144 (256 KiB) |
Maximum file size in bytes |
--max-body-size |
5242880 (5 MiB) |
Maximum request body size in bytes |
Request:
{
"runtime": "node",
"files": [
{
"name": "index.js",
"content": "Y29uc29sZS5sb2coIkhlbGxvLCBXb3JsZCEiKQ=="
}
]
}runtime(required): one of"node","ruby","go","bash"files(required): array of source files.contentis Base64-encoded. The first file in the array is used as the entrypoint
Response:
{
"compile": null,
"run": {
"stdout": "SGVsbG8sIFdvcmxkIQo=",
"stderr": "",
"output": "SGVsbG8sIFdvcmxkIQo=",
"exit_code": 0,
"status": "OK",
"signal": null
}
}compile: compilation result (same schema asrun).nullfor interpreted runtimes (node, ruby, bash). When compilation fails,runisnullrun: execution result.nullwhen compilation failsstdout/stderr/output: Base64-encoded output.outputis the interleaved combination of stdout and stderrexit_code: process exit codestatus: one of"OK","SIGNAL","TIMEOUT","OUTPUT_LIMIT_EXCEEDED"signal: signal name if the process was killed by a signal (e.g."SIGKILL"),nullotherwise
POST /v1/run
→ Echo HTTP server (request validation, Base64 decoding, write files to tmpdir)
→ nsjail (execute code in a namespace-isolated environment)
→ Return response
Code is isolated by google/nsjail with multiple layers of defense:
- Linux namespaces: PID, network, mount, UTS, IPC, and cgroup namespaces are all isolated. External network access is completely blocked, and loopback communication is also disabled.
- UID/GID mapping: Sandboxed processes run as nobody (65534). Only a single UID is mapped, making setuid impossible.
- Filesystem restrictions: Only the minimum required paths are mounted (shared libraries, device files, user code directory). Everything except the user code directory is read-only.
/tmpis a 64 MiB tmpfs mounted with noexec. - Resource limits: Execution time is enforced by nsjail's
--time_limitand--rlimit_cpu. Cgroups limit PID count, memory, and CPU usage. Rlimits constrain stack size and other per-process resources. - Seccomp-BPF: Dangerous syscalls (io_uring, bpf, mount, ptrace, unshare, etc.) are blocked at the kernel level. Clone calls with namespace creation flags are also blocked.
- Output limits: The process is killed if the combined stdout and stderr exceeds the configured limit.