# How to Configure the AxJSRuntime for Secure JavaScript Sandboxing in Ax

> Secure your Ax applications by configuring AxJSRuntime for robust JavaScript sandboxing. Block dangerous globals and grant selective permissions to enhance security.

- Repository: [Ax/ax](https://github.com/ax-llm/ax)
- Tags: how-to-guide
- Published: 2026-02-25

---

**The AxJSRuntime provides permission-based sandboxing that blocks all dangerous globals by default and allows selective capability grants via the AxJSRuntimePermission enum.**

The Ax framework (`ax-llm/ax`) includes a built-in JavaScript interpreter called **AxJSRuntime** that powers the Repl-like-Model (RLM) subsystem. This runtime executes model-generated code inside a locked-down sandbox that isolates execution from the host process through a deny-by-default permission system.

## Core Sandbox Architecture

### Permission-Based Capability Model

The runtime implements least-privilege security through the `AxJSRuntimePermission` enum defined in [`src/ax/funcs/jsRuntime.ts`](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/jsRuntime.ts). Rather than starting with full access and restricting, it begins with zero capabilities and requires explicit opt-in for every potentially dangerous operation.

```typescript
export enum AxJSRuntimePermission {
  /** fetch, XMLHttpRequest, WebSocket, EventSource */      NETWORK = 'network',
  /** indexedDB, caches */                                 STORAGE = 'storage',
  /** importScripts */                                    CODE_LOADING = 'code-loading',
  /** BroadcastChannel */                                 COMMUNICATION = 'communication',
  /** performance */                                      TIMING = 'timing',
  /** Worker, SharedWorker (brings all above capabilities) */ WORKERS = 'workers',
}

```

*Source: [jsRuntime.ts – Permission enum](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/jsRuntime.ts#L75-L92)*

### Constructor Configuration Options

When instantiating the runtime, you pass an options object to the constructor. The most critical fields for sandboxing control are:

- `permissions?: readonly AxJSRuntimePermission[]` – The allow-list of capabilities.
- `allowUnsafeNodeHostAccess?: boolean` – **Dangerous** flag that grants access to Node.js globals like `process` and `require`. Defaults to `false`.
- `outputMode?: 'return' | 'stdout'` – Determines whether results are collected from `return` statements or `console.log` output.
- `captureConsole?: boolean` – Automatically captures `console.*` output when `outputMode` is `'stdout'`.

The constructor signature in [`src/ax/funcs/jsRuntime.ts`](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/jsRuntime.ts) (lines 11-28) accepts:

```typescript
constructor(options?: {
  timeout?: number;
  permissions?: readonly AxJSRuntimePermission[];
  outputMode?: AxJSRuntimeOutputMode;
  captureConsole?: boolean;
  allowUnsafeNodeHostAccess?: boolean;
  nodeWorkerPoolSize?: number;
  debugNodeWorkerPool?: boolean;
})

```

### Worker-Based Isolation

The runtime creates a **Web-Worker-compatible** session via `createSession`. In browser environments it uses native `Worker` instances; in Node.js it falls back to `worker_threads`. During initialization, the worker receives the permission list through an `init` message, and the sandbox implementation inside [`worker.runtime.ts`](https://github.com/ax-llm/ax/blob/main/worker.runtime.ts) enforces those restrictions by deleting unauthorized globals from the worker's environment.

## Available Permissions and Security Implications

- **NETWORK** – Grants access to `fetch`, `XMLHttpRequest`, `WebSocket`, and `EventSource` for external data retrieval.
- **STORAGE** – Enables `indexedDB` and `caches` for client-side data persistence.
- **CODE_LOADING** – Allows `importScripts` for dynamically loading additional code.
- **COMMUNICATION** – Permits `BroadcastChannel` for cross-context messaging.
- **TIMING** – Exposes the `performance` object for high-resolution timing.
- **WORKERS** – Enables `Worker` and `SharedWorker` instantiation. **Warning:** This implicitly grants all other capabilities inside spawned sub-workers because they initialize with a fresh global environment containing all permissions.

**Critical Safety Note:** The `allowUnsafeNodeHostAccess` option should **never** be enabled in multi-tenant or untrusted scenarios. When set to `true`, sandboxed code can access the host Node.js process, filesystem, and native modules.

## Configuration Examples

### Minimal Sandbox (Default)

Omitting the `permissions` array creates the tightest sandbox, blocking all external I/O.

```typescript
import { AxJSRuntime, agent } from '@ax-llm/ax';

const runtime = new AxJSRuntime();  // No permissions = safest sandbox
const myAgent = agent(
  'input:string -> output:string',
  { runtime }
);

```

### Network and Timing Access

Enable `fetch` and `performance.now()` for agents that need to download data and measure execution time:

```typescript
import {
  AxJSRuntime,
  AxJSRuntimePermission,
  agent,
} from '@ax-llm/ax';

const runtime = new AxJSRuntime({
  permissions: [
    AxJSRuntimePermission.NETWORK,   // Allow fetch / XMLHttpRequest
    AxJSRuntimePermission.TIMING,    // Allow performance.now()
  ],
});

const analyzer = agent(
  'context:string, query:string -> answer:string, evidence:string[]',
  {
    runtime,
    maxSteps: 10,
  }
);

```

*Source: [examples/rlm.ts – Runtime configuration](https://github.com/ax-llm/ax/blob/main/src/examples/rlm.ts#L22-L25)*

### Storage and Sub-Workers (Advanced)

Persist intermediate results with IndexedDB while using parallel workers:

```typescript
const runtime = new AxJSRuntime({
  permissions: [
    AxJSRuntimePermission.STORAGE,   // IndexedDB / cache access
    AxJSRuntimePermission.WORKERS,   // Sub-workers (implies all capabilities)
  ],
  outputMode: 'return',              // Collect via return value
});

```

### Unsafe Node Host Access (Internal Only)

For trusted internal tooling where sandboxed code must interact with the host Node.js environment:

```typescript
const runtime = new AxJSRuntime({
  allowUnsafeNodeHostAccess: true,    // Exposes require, process, etc.
});

```

**Never use this configuration for untrusted or AI-generated code.**

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`src/ax/funcs/jsRuntime.ts`](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/jsRuntime.ts) | Core `AxJSRuntime` implementation, permission enum, and constructor logic. |
| [`src/examples/rlm.ts`](https://github.com/ax-llm/ax/blob/main/src/examples/rlm.ts) | Real-world demonstration of passing permission arrays to the runtime. |
| [`src/ax/funcs/worker.runtime.ts`](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/worker.runtime.ts) | Worker-side code that enforces permission restrictions by manipulating globals. |
| [`src/ax/funcs/jsRuntime.test.ts`](https://github.com/ax-llm/ax/blob/main/src/ax/funcs/jsRuntime.test.ts) | Test suite verifying sandbox restrictions and permission boundaries. |

## Summary

- **AxJSRuntime** uses a deny-by-default security model where all dangerous globals are blocked unless explicitly permitted.
- Configure capabilities through the `permissions` array using the `AxJSRuntimePermission` enum.
- The runtime executes code inside isolated Web Workers (or Node.js `worker_threads`) to separate execution contexts from the host process.
- Enabling `AxJSRuntimePermission.WORKERS` implicitly grants all other permissions to any spawned sub-workers.
- The `allowUnsafeNodeHostAccess` flag bypasses all protections and should only be used for trusted internal scripts.

## Frequently Asked Questions

### What permissions does AxJSRuntime block by default?

By default, the runtime blocks all potentially unsafe globals including `fetch`, `indexedDB`, `importScripts`, `WebSocket`, and `BroadcastChannel`. If you instantiate `new AxJSRuntime()` without a `permissions` array, the sandbox provides only pure computational access with no network, storage, or timing capabilities.

### How do I enable network requests in the sandbox?

Import `AxJSRuntimePermission.NETWORK` and include it in the permissions array: `new AxJSRuntime({ permissions: [AxJSRuntimePermission.NETWORK] })`. This grants access to `fetch`, `XMLHttpRequest`, `WebSocket`, and `EventSource` while maintaining restrictions on file system and host process access.

### Is AxJSRuntime safe for running untrusted AI-generated code?

Yes, when configured with the default settings (no permissions and `allowUnsafeNodeHostAccess: false`), the runtime provides a secure sandbox suitable for executing untrusted code. The worker-based isolation prevents access to the host process, and the permission system blocks external I/O. Never enable `allowUnsafeNodeHostAccess` for untrusted inputs.

### What is the difference between the WORKERS permission and other permissions?

While other permissions grant specific capabilities like network or storage access, `AxJSRuntimePermission.WORKERS` enables the creation of sub-workers via `new Worker()` or `new SharedWorker()`. Because these sub-workers initialize with a fresh global environment, they implicitly receive all other capabilities (network, storage, timing, etc.) regardless of the parent runtime's permission settings.