Alle Artikel

Artikel

Running TypeScript in a Sandbox: A Deep Dive into QuickJS and WebAssembly

How to run user-provided or AI-generated JavaScript and TypeScript in a controlled QuickJS WebAssembly guest runtime with explicit host capabilities.

Modern products increasingly need to execute code they did not write themselves: customer automation, data transforms, plugin hooks, playgrounds, and AI-generated snippets. The hard part is not running JavaScript. The hard part is deciding exactly what the guest code may touch.

The Challenge

Traditional approaches like eval() or new Function() run inside the same application context. That is unacceptable for enterprise workflows where code execution must be observable, bounded, and separated from host APIs.

QuickJS to the Rescue

QuickJS is a small embeddable JavaScript engine by Fabrice Bellard. The package wraps a QuickJS WebAssembly runtime and exposes explicit options for the capabilities guest code may receive.

That distinction matters. This is a controlled guest runtime, not a magic security product. In production, it should be combined with worker, process, or container isolation, logging, and egress policy.

Architecture

The project is built around a few concrete boundaries:

  1. QuickJS WebAssembly runtime: JavaScript and transformed TypeScript execute in a guest runtime.
  2. Host capability gates: Environment values, fetch, filesystem access, and mounted modules are only exposed when configured.
  3. Execution bounds: Options such as executionTimeout, memoryLimit, maxStackSize, maxTimeoutCount, and maxIntervalCount limit common runaway scenarios.
  4. Result protocol: Code can return a default export or structured value to the host instead of mutating host state directly.

Implementation Details

The key is creating a minimal but useful API surface:

interface SandboxOptions {
  executionTimeout?: number;
  memoryLimit?: number;
  maxStackSize?: number;
  env?: Record<string, string>;
  allowFetch?: boolean;
  allowFs?: boolean;
}

Use Cases

This runtime is useful for:

  • Product automation where customers bring small snippets
  • AI-generated data transformation code that needs a controlled execution surface
  • Code playgrounds and REPLs
  • Plugin systems where host APIs should be explicit
  • Browser and Node.js use cases that need similar execution semantics

Try It Out

You can try the sandbox at sebastianwessel.github.io/quickjs or check out the source on GitHub.