Skip to main content

Install

npm install secure-exec

Core concepts

Every sandbox has two layers:
  • System driver provides host capabilities: filesystem, network, child processes, and permissions.
  • The execution environment runs code in a V8 isolate (Node) or Web Worker (browser).
All host capabilities are deny-by-default. You opt in to what sandboxed code can access.

Create a runtime

import {
  NodeRuntime,
  createNodeDriver,
  createNodeRuntimeDriverFactory,
} from "secure-exec";

const runtime = new NodeRuntime({
  systemDriver: createNodeDriver(),
  runtimeDriverFactory: createNodeRuntimeDriverFactory(),
});

Execute code

Two methods for running sandboxed code:
// exec() runs code for side effects, returns an exit code
const execResult = await runtime.exec("console.log('hello')");
console.log(execResult.code); // 0

// run() runs code and returns the default export
const runResult = await runtime.run<{ default: number }>(
  "export default 2 + 2"
);
console.log(runResult.exports?.default); // 4

Capture output

Console output is not buffered by default. Use the onStdio hook to capture it:
const logs: string[] = [];

await runtime.exec("console.log('hello'); console.error('oops')", {
  onStdio: (event) => logs.push(`[${event.channel}] ${event.message}`),
});

// logs: ["[stdout] hello", "[stderr] oops"]
You can also set a default hook on the runtime:
const runtime = new NodeRuntime({
  systemDriver: createNodeDriver(),
  runtimeDriverFactory: createNodeRuntimeDriverFactory(),
  onStdio: (event) => console.log(event.message),
});
See Output Capture for more patterns.

TypeScript

Optional companion package for sandboxed type checking and compilation:
pnpm add @secure-exec/typescript
import { createTypeScriptTools } from "@secure-exec/typescript";

const ts = createTypeScriptTools({
  systemDriver: createNodeDriver(),
  runtimeDriverFactory: createNodeRuntimeDriverFactory(),
});
const result = await ts.typecheckSource({
  sourceText: "const x: number = 'hello';",
});

console.log(result.success); // false
console.log(result.diagnostics[0].message);
// "Type 'string' is not assignable to type 'number'."
See TypeScript.

Permissions

All capabilities are blocked unless you opt in:
import { createNodeDriver, allowAll, allowAllFs } from "secure-exec";

// Allow everything
const driver = createNodeDriver({ permissions: allowAll });

// Allow only filesystem
const fsOnly = createNodeDriver({ permissions: { fs: allowAllFs } });

// Custom check
const filtered = createNodeDriver({
  permissions: {
    network: (req) => req.hostname !== "internal.corp",
  },
});
See Permissions for the full API.

Resource limits

Prevent runaway execution with CPU and memory bounds:
const runtime = new NodeRuntime({
  systemDriver: createNodeDriver(),
  runtimeDriverFactory: createNodeRuntimeDriverFactory(),
  memoryLimit: 64, // MB
  cpuTimeLimitMs: 5000,
});
See Resource Limits for payload limits and per-execution overrides.

Filesystem

import { createNodeDriver, allowAllFs } from "secure-exec";

const driver = createNodeDriver({
  permissions: { fs: allowAllFs },
});
Three filesystem backends are available: Node.js host fs, in-memory, and OPFS (browser). See Filesystem.

Networking

import { createNodeDriver, allowAllNetwork } from "secure-exec";

const driver = createNodeDriver({
  useDefaultNetwork: true,
  permissions: { network: allowAllNetwork },
});
See Networking.

Clean up

runtime.dispose();

Next steps

Runtimes

Node runtime details.

System Drivers

Configure host capabilities per environment.

Security Model

Trust boundaries, timing hardening, and isolation guarantees.

API Reference

Complete type and method reference.