Blog/Engineering

Building a sandboxed code execution engine for 8 languages

How we safely run untrusted user code using child_process, SIGKILL timeouts, and output caps.

M

Marcus R.

Infrastructure and runtime security at Collab.Code.

Apr 29, 2026

14 min read

Why not Docker on every request?

Container startup latency (300–800ms) is unacceptable for an interactive editor. We use Node.js child_process.spawn with strict constraints instead, reserving Docker for long-running or high-privilege execution.

The execution contract

Every run gets: 8-second wall-clock timeout (SIGTERM → SIGKILL), 50KB stdout/stderr cap, a temp directory cleaned up post-execution, and no network access (resolved at OS level). Language processes are spawned as a restricted user.

javascript
const child = spawn(cmd, args, {
  timeout: 8000,
  cwd: tmpDir,
  env: {
    PATH: SAFE_PATH,
    HOME: tmpDir,
    // no network, no secrets
  },
})

child.stdout.on('data', (d) => {
  output += d
  if (output.length > 50_000) child.kill('SIGKILL')
})

Supporting 8 languages

Python (3.12), JavaScript (Node 22), TypeScript (ts-node), Go (1.22), Rust (1.77), Java (21), C++ (g++14), Bash. Each language has its own runner config — compilation languages get a compile step with separate timeout, then execution.

M

Marcus R.

Infrastructure and runtime security at Collab.Code.

Related posts

Try Collab.Code

Real-time collaboration, AI review, and sandboxed execution — Pro $30/mo, Enterprise $100/mo.

Get started — $30/mo
Building a sandboxed code execution engine for 8 languages | Collab.Code