run

run executes untrusted JavaScript and type-stripped TypeScript in a hardened QuickJS sandbox. Guest code can access only the host functions you provide.

Quick start

pnpm add run

Supports Node.js 22.13 or newer and Bun.

import { run } from 'run';

const result = await run({
  source: `
    const orders = await store.listOrders('customer_123');
    return orders.reduce((total, order) => total + order.amount, 0);
  `,
  hostFunctions: {
    store: {
      listOrders: (customerId: string) =>
        database.orders.findMany({ customerId }),
    },
  },
});

if (result.status === 'completed') {
  console.log(result.value);
}

The generated program can call store.listOrders(), while the database client and its credentials stay in your application.

Features

  • Every invocation gets a fresh QuickJS context in a worker thread, with no ambient Node.js, filesystem, module, or network access.
  • A host function can interrupt a run for approval or authentication. The run resumes without repeating host calls that already completed.
  • Time, memory, result size, and concurrency are capped, per run or per runner.

run is for sandboxed JavaScript computation inside an application. Workloads that need an operating system, package installation, or process-level isolation should use Vercel Sandbox.

Documentation

Start with the introduction, then the foundations and the API reference.

Development

pnpm test:watch runs tests directly against TypeScript source, including the embedded worker and guest serialization code. Source edits rerun affected tests without a package build or a dist directory. Use pnpm --filter run test:node for a single source test run.

pnpm test runs the source suite, then builds and runs the full suite against the shipped worker bundle, including hardening and package distribution tests. pnpm --filter run test:package (also test:hardening) runs this build-backed suite directly. Bare vitest commands use the source setup; --mode package selects the built worker and requires a package build first.

pnpm check runs formatting, static analysis, and the fail-closed banned-pattern security scan. A local @banned-pattern-ignore is accepted only when it states a concrete safety reason and suppresses an actual finding; stale suppressions fail the scan.

License

Apache 2.0