Isolation Model
Runra Sandbox provides VM-backed isolation for every sandbox. This means each sandbox runs in its own virtual machine, not just a container — giving you stronger security boundaries than container-based solutions.
VM-backed execution
Section titled “VM-backed execution”Each sandbox runs inside a dedicated VM provisioned by CubeSandbox, the open-source engine that powers Runra. This provides:
- Kernel-level isolation: Separate kernel instances prevent privilege escalation between sandboxes
- No shared OS state:
/proc,/sys, and other kernel interfaces are sandbox-private - Guaranteed resource allocation: CPU cores and memory pages are assigned per VM, not shared
┌─────────────────────────────────────────────┐│ Host Node ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ Sandbox A│ │ Sandbox B│ │ Sandbox C│ ││ │ VM #1 │ │ VM #2 │ │ VM #3 │ ││ │ CPU: 2 │ │ CPU: 4 │ │ CPU: 8 │ ││ │ RAM: 4GB │ │ RAM: 8GB │ │ RAM:16GB │ ││ └──────────┘ └──────────┘ └──────────┘ ││ ↕ ↕ ↕ ││ ┌──────────────────────────────────────┐ ││ │ CubeProxy (network layer) │ ││ └──────────────────────────────────────┘ │└─────────────────────────────────────────────┘File system isolation
Section titled “File system isolation”Every sandbox gets its own private filesystem workspace. There is no shared filesystem between sandboxes:
const sandboxA = await runra.sandboxes.create({ image: "node:22" });const sandboxB = await runra.sandboxes.create({ image: "node:22" });
await sandboxA.files.write("/workspace/secret.txt", "token-abc");await sandboxB.files.write("/workspace/secret.txt", "token-xyz");
// Each sandbox only sees its own fileconst a = await sandboxA.files.read("/workspace/secret.txt"); // "token-abc"const b = await sandboxB.files.read("/workspace/secret.txt"); // "token-xyz"Workspace structure
Section titled “Workspace structure”/workspace/ ← Your sandbox workspace (persisted across pause/resume)├── app/ ← Your application code├── node_modules/ ← Dependencies (preserved on pause)└── .../tmp/ ← Ephemeral temp (cleared on sandbox restart)File operations
Section titled “File operations”All standard file operations go through the sandbox API:
// Write a fileawait sandbox.files.write("/workspace/app.ts", content);
// Read a fileconst content = await sandbox.files.read("/workspace/app.ts");
// List directoryconst files = await sandbox.files.list("/workspace");
// Check if existsconst exists = await sandbox.files.exists("/workspace/app.ts");
// Delete a fileawait sandbox.files.delete("/workspace/temp.log");
// Create directoryawait sandbox.files.mkdir("/workspace/src/components");Process isolation
Section titled “Process isolation”Processes in one sandbox cannot see or interact with processes in another:
// Sandbox A runs a serverawait sandboxA.exec("python -m http.server 8000 &");
// Sandbox B cannot see the server processconst result = await sandboxB.exec("ps aux");// Shows only sandbox B's processes — no http.server from sandbox AEach sandbox has its own PID namespace, mount namespace, and IPC namespace — standard Linux namespace isolation reinforced by the VM boundary.
Resource limits
Section titled “Resource limits”Every sandbox has hard resource limits that cannot be exceeded:
| Resource | Default | Max | Description |
|---|---|---|---|
| CPU cores | 2 | 8 | Dedicated vCPUs |
| Memory | 4096 MB | 16384 MB | Hard limit, OOM kill on exceed |
| Disk | 10240 MB | 51200 MB | Workspace storage |
| Processes | 256 | 1024 | Max simultaneous processes |
const sandbox = await runra.sandboxes.create({ image: "node:22", resources: { cpu: 4, // 4 dedicated vCPUs memoryMb: 8192, // 8 GB RAM (hard limit) diskMb: 20480, // 20 GB disk },});If a sandbox exceeds its memory limit, the kernel OOM killer terminates the offending process. If CPU usage is sustained at 100%, the VM is throttled to its allocated cores — no noisy neighbor problems.
Network policy
Section titled “Network policy”Network access is controlled per sandbox:
const sandbox = await runra.sandboxes.create({ image: "node:22", network: { // Allow outbound to specific hosts egress: { allow: ["github.com", "registry.npmjs.org", "api.openai.com"], // Block everything else default: "deny", }, // Inbound is only through exposed ports ingress: { allowPorts: [3000, 8080], }, },});Default network policy
Section titled “Default network policy”| Direction | Default | Description |
|---|---|---|
| Outbound (egress) | Allow all | Sandbox can reach any internet host |
| Inbound (ingress) | Deny all | Only ports explicitly exposed are accessible |
| Sandbox-to-sandbox | Deny | Sandboxes cannot communicate with each other |
Port exposure
Section titled “Port exposure”Only explicitly exposed ports are reachable from the internet:
// Expose port 3000 — generates a public URLconst port = await sandbox.exposePort(3000);console.log(port.url); // https://3000-abc123.box.runra.devSee Exposing Ports for the full port exposure guide.
Timeout and lifecycle controls
Section titled “Timeout and lifecycle controls”Prevent runaway sandboxes with automatic lifecycle controls:
const sandbox = await runra.sandboxes.create({ image: "node:22", timeoutMs: 300_000, // Auto-terminate after 5 minutes (hard limit) idleTimeoutMs: 120_000, // Auto-pause after 2 minutes of inactivity});Timeout types
Section titled “Timeout types”| Timeout | Trigger | Action |
|---|---|---|
timeoutMs | Total sandbox lifetime exceeded | Force terminate |
idleTimeoutMs | No exec calls for specified duration | Auto-pause |
| Per-command timeout | Individual exec() takes too long | Abort command, sandbox stays running |
// Per-command timeoutconst result = await sandbox.exec("npm run long-build", { timeoutMs: 60_000, // Kill if build takes more than 60 seconds});Disposable environments
Section titled “Disposable environments”Every sandbox is disposable by design. Terminate cleans up all resources immediately:
await sandbox.terminate();// VM destroyed, disk wiped, ports released, IP recycledNo data persists after termination. If you need state to survive, use pause instead.
Security guarantees
Section titled “Security guarantees”Runra Sandbox provides these security guarantees:
- No cross-sandbox access: Sandbox A cannot read Sandbox B’s files, processes, or network traffic
- No host escape: VM isolation prevents escape to the host node
- No resource stealing: Hard resource limits prevent one sandbox from starving others
- No persistent side effects: Termination wipes everything
- Network control: You control what each sandbox can reach
Next steps
Section titled “Next steps”- Pause & Resume — state preservation without active risk
- Exposing Ports — secure network exposure
- Setup Guide — configure resource limits in production