Skip to content
GitHub Get Started
Reference

Secure Exec vs Container Sandbox

Secure Exec and container sandboxes both run untrusted code in isolation, but they sit at different points on the weight-versus-flexibility curve. Picking the right one depends on what you need to run.

Secure Exec boots a fully virtualized VM for each runtime and runs guest JavaScript in a V8 isolate inside a dedicated sidecar process. There is no Docker daemon, no orchestrator, and no vendor account: you npm install the package and call NodeRuntime.create(). It is built for lightweight, high-fanout code execution like AI tool calls, user scripts, and plugins, where you want granular permissions and a small footprint.

Container sandboxes (e2b, Daytona, Modal, Cloudflare Containers, and similar) spin up a full OS image with system packages, a writable disk, and the ability to run arbitrary binaries. They are built for heavyweight workloads that need a complete environment: coding agents, long-lived dev sessions, or anything that shells out to native tools.

The biggest difference is what the isolation boundary is made of.

  • Secure Exec runs guest code in a V8 isolate hosted by its own sidecar process. Every NodeRuntime.create() is a separate VM with its own virtual filesystem, process table, network policy, and crash domain. Guest code never calls real Node.js builtins, never opens a real host socket, and never touches the real disk. Every syscall is routed through the kernel. See Process Isolation.
  • Container sandboxes isolate with OS-level primitives (namespaces, cgroups, or a microVM). The guest runs a real kernel and a real filesystem, so it can do anything a Linux process can, constrained by the container’s configuration.

Secure Exec presents normal Linux semantics to the code it runs (a POSIX-like virtual filesystem, processes, pipes, PTYs, sockets) without granting access to the host that backs them.

DimensionSecure ExecContainer Sandbox
Isolation boundaryVirtualized VM + V8 isolate in a sidecar processOS container or microVM
Setupnpm install secure-execVendor account or Docker host
HardwareRuns on your infrastructureOften vendor-hosted
FilesystemVirtual, in-memory, per runtimeFull OS filesystem
NetworkDenied by default, opt-in per runtimeFull, or firewall rules
PermissionsPer-scope policy (fs, network, childProcess, process, env, tool)Coarse, container-level
LanguagesJavaScript and TypeScript (Node-compatible)Any language the image supports
Arbitrary binariesNo (guest binaries run through the VM, not the host)Yes
Crash domainOne process per runtimeOne container per sandbox

These capabilities are the reason to reach for Secure Exec over a container when the workload fits in a Node-compatible runtime:

  • Deny-by-default permissions. Network egress is blocked until you opt in, and every guest syscall is checked against a per-scope policy before any host resource is touched. A denied operation fails with EACCES. See Permissions.
  • Virtual filesystem. Each runtime gets its own in-memory filesystem. Guest reads and writes never reach the host disk, and two runtimes writing the same path do not collide. See Filesystem.
  • Mediated networking. Guest fetch(), node:http, and raw sockets all flow through the kernel socket table, so you can allow, deny, or rule-match outbound traffic. See Networking.
  • Process-level isolation. Each runtime is its own VM and its own crash domain, and each exec() / run() starts a fresh guest process so in-memory state never leaks between runs. See Process Isolation.
  • npm compatibility. Real npm packages run unmodified inside the VM, resolved over a faithfully mounted node_modules like a real filesystem. See Module Loading.
  • You are running JavaScript or TypeScript (AI tool calls, user scripts, plugins, evaluation loops).
  • You want no vendor dependency and to run on your own infrastructure.
  • You need granular, deny-by-default permissions over the filesystem, network, and child processes.
  • You are running many short tasks and want a small per-task footprint.
  • You need a full OS environment: system packages, arbitrary binaries, or languages beyond a Node-compatible runtime.
  • You need a persistent, long-lived environment such as a multi-hour dev session.
  • The workload genuinely needs a real kernel and a real disk.

Booting a Secure Exec runtime takes no infrastructure beyond the installed package. The runtime owns its VM until you dispose it:

import { NodeRuntime } from "secure-exec";
// Network is denied by default; the guest runs in its own virtualized VM.
const rt = await NodeRuntime.create();
try {
const result = await rt.run<number>(`
__return(40 + 2);
`);
console.log(result.value); // 42
} finally {
await rt.dispose();
}

There is no container to build, no image to pull, and no daemon to keep running.

Because there is no container image or microVM to boot, a Secure Exec runtime starts in a fraction of the time a container takes, and the dominant cost is bringing up the guest runtime rather than provisioning infrastructure. For workloads that run the same kind of snippet repeatedly, reusing a live guest process drives warm execution into the low-millisecond range. See Benchmarks for measured cold-start, warm, and reuse numbers and the methodology behind them.