# @suaveplan/sandbox - Server-tier sandboxed code execution: node:vm, node:worker_threads, and node:child_process engines, pre-warmed pool, audit logger, sliding-window rate limiter, pattern-based code transformer, async result streamer. Server-tier sandboxed code execution for `@suaveplan` plugin hosts and agent runtimes. Ships four `SandboxEngine` implementations (a `node:vm` default, real `node:worker_threads` for OS-thread isolation, real `node:child_process` for process isolation, and a structural `isolated-vm` adapter), a pre-warmed `SandboxPool`, an async `ResultStreamer`, a pattern-based `CodeTransformer`, an allowlist-based `ModuleResolver`, a sliding-window `ResourceLimiter`, and a SHA-256 `AuditLogger` — all behind a `createSandbox()` facade with Zod-validated config and full OpenTelemetry instrumentation. ## Documentation tree - [audit-logger](./src/audit-logger/audit-logger.md) — `AuditLogger` records every sandbox execution with a structured `AuditLogEntry`. Each entry carries an ISO-8601 timesta… - [audit-logger](./src/audit-logger/audit-logger.md) — `AuditLogger` records every sandbox execution with a structured `AuditLogEntry`. Each entry carries an ISO-8601 timesta… - [code-transformer](./src/code-transformer/code-transformer.md) — `CodeTransformer` is a defence-in-depth layer that pattern-matches dangerous code constructs before they reach the engi… - [code-transformer](./src/code-transformer/code-transformer.md) — `CodeTransformer` is a defence-in-depth layer that pattern-matches dangerous code constructs before they reach the engi… - [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/sandbox` raises typed `SandboxError` instances rather than plain `Error` so consumers can discriminate fail… - [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/sandbox` raises typed `SandboxError` instances rather than plain `Error` so consumers can discriminate fail… - [isolate-engine](./src/isolate-engine/isolate-engine.md) — `IsolateEngine` implements the `SandboxEngine` contract over a structural `IsolateFactory` interface that mirrors the `… - [isolate-engine](./src/isolate-engine/isolate-engine.md) — `IsolateEngine` implements the `SandboxEngine` contract over a structural `IsolateFactory` interface that mirrors the `… - [module-resolver](./src/module-resolver/module-resolver.md) — `ModuleResolver` is the gatekeeper between user code and the host's module surface. It maintains an allowlist of module… - [module-resolver](./src/module-resolver/module-resolver.md) — `ModuleResolver` is the gatekeeper between user code and the host's module surface. It maintains an allowlist of module… - [pool](./src/pool/pool.md) — `SandboxPool` amortises engine startup cost across many short executions by maintaining a warm pool of `SandboxEngine`… - [pool](./src/pool/pool.md) — `SandboxPool` amortises engine startup cost across many short executions by maintaining a warm pool of `SandboxEngine`… - [resource-limiter](./src/resource-limiter/resource-limiter.md) — `ResourceLimiter` enforces two complementary controls on the sandbox boundary: a sliding-window rate limit (so a single… - [resource-limiter](./src/resource-limiter/resource-limiter.md) — `ResourceLimiter` enforces two complementary controls on the sandbox boundary: a sliding-window rate limit (so a single… - [result-streamer](./src/result-streamer/result-streamer.md) — `ResultStreamer` delivers sandbox output incrementally rather than as a single end-of-execution dump. The most common u… - [result-streamer](./src/result-streamer/result-streamer.md) — `ResultStreamer` delivers sandbox output incrementally rather than as a single end-of-execution dump. The most common u… - [sandbox](./src/sandbox/sandbox.md) — `createSandbox` is the public entry point of the package. It composes the engine, `ModuleResolver`, `ResourceLimiter`,… - [sandbox](./src/sandbox/sandbox.md) — `createSandbox` is the public entry point of the package. It composes the engine, `ModuleResolver`, `ResourceLimiter`,… - [schemas](./src/schemas/schemas.md) — Zod schemas guard every public boundary of `@suaveplan/sandbox`. The package never trusts its caller; instead, every ar… - [schemas](./src/schemas/schemas.md) — Zod schemas guard every public boundary of `@suaveplan/sandbox`. The package never trusts its caller; instead, every ar… - [spawn-engine](./src/spawn-engine/spawn-engine.md) — `SpawnEngine` uses `node:child_process.spawn` for the strongest isolation the package offers: a fresh OS process spawne… - [runner](./src/spawn-engine/runner.md) — `runner.ts` is the child-process entry point invoked by `SpawnEngine`. The parent process spawns it via `node:child_pro… - [spawn-engine](./src/spawn-engine/spawn-engine.md) — `SpawnEngine` uses `node:child_process.spawn` for the strongest isolation the package offers: a fresh OS process spawne… - [telemetry](./src/telemetry/telemetry.md) — `@suaveplan/sandbox` ships first-class OpenTelemetry instrumentation so consumers running the sandbox at any scale can… - [telemetry](./src/telemetry/telemetry.md) — `@suaveplan/sandbox` ships first-class OpenTelemetry instrumentation so consumers running the sandbox at any scale can… - [vm-engine](./src/vm-engine/vm-engine.md) — `VmEngine` is the default sandbox engine. It uses `node:vm` directly: caller code is compiled with `new vm.Script(...)`… - [vm-engine](./src/vm-engine/vm-engine.md) — `VmEngine` is the default sandbox engine. It uses `node:vm` directly: caller code is compiled with `new vm.Script(...)`… - [worker-engine](./src/worker-engine/worker-engine.md) — `WorkerEngine` uses real `node:worker_threads` for true OS-thread isolation. Each `execute` call spawns a fresh `Worker… - [worker-engine](./src/worker-engine/worker-engine.md) — `WorkerEngine` uses real `node:worker_threads` for true OS-thread isolation. Each `execute` call spawns a fresh `Worker… ## Install ```bash bun add @suaveplan/sandbox ``` ## Quick start ```ts import { createSandbox } from "@suaveplan/sandbox"; const sandbox = createSandbox({ timeout: 5000, engine: "vm" }); const result = await sandbox.execute("2 + 3"); console.log(result.result); // 5 sandbox.destroy(); ``` ## Engine selection | Engine | Boundary | Use when | |---|---|---| | `vm` (default) | `node:vm` context | Trusted accident-isolation, fastest path. | | `worker` | `node:worker_threads` | Adversarial code, OS-thread isolation. | | `spawn` | `node:child_process` | Adversarial code, full process isolation. | | `isolate` | `isolated-vm` (optional dep) | Strongest in-process isolation. | Wire `engine: "isolate"` with a `customEngine` factory that constructs a real `IsolateEngine` over your installed `isolated-vm` peer dependency. ## Modules Co-located docs for every public surface: - [error-codes](./src/error-codes/error-codes.md) — `SANDBOX_CODES`, `SandboxError`. - [schemas](./src/schemas/schemas.md) — Zod boundaries. - [telemetry](./src/telemetry/telemetry.md) — OTel instruments + recorders. - [audit-logger](./src/audit-logger/audit-logger.md) — execution audit log. - [resource-limiter](./src/resource-limiter/resource-limiter.md) — rate-limit + output truncation. - [module-resolver](./src/module-resolver/module-resolver.md) — denylist/allowlist + builtins. - [code-transformer](./src/code-transformer/code-transformer.md) — regex-based dangerous-pattern guard. - [vm-engine](./src/vm-engine/vm-engine.md) — default engine. - [worker-engine](./src/worker-engine/worker-engine.md) — OS-thread engine. - [spawn-engine](./src/spawn-engine/spawn-engine.md) — process engine. - [runner](./src/spawn-engine/runner.md) — spawn-engine child entry point. - [isolate-engine](./src/isolate-engine/isolate-engine.md) — `isolated-vm` structural adapter. - [pool](./src/pool/pool.md) — pre-warmed engine pool. - [result-streamer](./src/result-streamer/result-streamer.md) — async streaming output. - [sandbox](./src/sandbox/sandbox.md) — `createSandbox` facade. ## Security model `vm-engine` shares the host realm and is NOT a security boundary against adversarial code — `vm.runInContext` can be escaped via prototype-chain tricks. For adversarial isolation, use `worker-engine` or `spawn-engine`, both of which sit behind real OS-level boundaries. The `code-transformer` is a defence-in-depth layer that catches the obvious accidents (`process.exit`, `require`, `eval`, etc.); it is not a substitute for an engine-level boundary. ## Tier Server (`node:vm` / `node:worker_threads` / `node:child_process` / `node:crypto`). Targets Node ≥ 20 (and Bun, which provides the same APIs).