Skip to main content
@enclave-vm/browser brings Enclave’s defense-in-depth security model to the browser. Instead of Node.js VM contexts, it uses a double iframe architecture with CSP isolation, prototype freezing, and secure proxies to safely execute untrusted and LLM-generated code entirely client-side.

AST Validation

Block dangerous constructs before execution using ast-guard’s AgentScript preset

Code Transformation

Automatically transform code for safe execution with proxied functions and loop limits

Double Iframe Sandbox

Execute in nested iframe isolation with CSP, sandbox attributes, and secure proxies

When to Use Browser Enclave

  • Client-side AI code execution — Run LLM-generated code in the browser without a server round-trip
  • No server required — All sandboxing happens in the browser via iframe isolation
  • Interactive code playgrounds — Build code editors with live execution and tool integration
  • Edge and offline scenarios — Execute sandboxed code without network connectivity
  • Rapid prototyping — Let users experiment with AgentScript in the browser

Browser vs Node.js

Feature@enclave-vm/core@enclave-vm/browser
RuntimeNode.js (vm module)Browser (iframe srcdoc)
IsolationDouble VM nestingDouble iframe nesting
Network blockingVM context restrictionCSP default-src 'none'
Eval blockingcodeGeneration: { strings: false }CSP blocks eval/Function
Worker poolworker_threads adapterNot available
AI scoring gateSupportedNot available
Reference sidecarSupportedNot available
Memory trackingV8 heap statsSoft estimation (String/Array hooks)
AST validationSame (@enclave-vm/ast)Same (@enclave-vm/ast)
Code transformationSame (AgentScript)Same (AgentScript)
Security levelsSame 4 levelsSame 4 levels
Tool systemSame callTool() APISame callTool() API

Installation

npm install @enclave-vm/browser

Quick Start

import { BrowserEnclave } from '@enclave-vm/browser';

// Create an enclave with a tool handler
const enclave = new BrowserEnclave({
  securityLevel: 'STANDARD',
  timeout: 10000,
  maxToolCalls: 50,
  toolHandler: async (toolName, args) => {
    const response = await fetch(`/api/tools/${toolName}`, {
      method: 'POST',
      body: JSON.stringify(args),
    });
    return response.json();
  },
});

// Execute AgentScript code
const result = await enclave.run(`
  const users = await callTool('users:list', { limit: 10 });
  const active = users.filter(u => u.active);
  return active.length;
`);

if (result.success) {
  console.log('Result:', result.value);
  console.log('Duration:', result.stats.duration, 'ms');
} else {
  console.error('Error:', result.error.message);
}

// Clean up
enclave.dispose();

Execution Results

Every call to run() returns a structured result with success/error status and execution statistics:
interface ExecutionResult<T> {
  success: boolean;
  value?: T;              // Result value (if success)
  error?: {               // Error details (if failed)
    name: string;
    message: string;
    code?: string;
    stack?: string;
    data?: Record<string, unknown>;
  };
  stats: {
    duration: number;      // Execution time in ms
    toolCallCount: number; // Number of tool calls made
    iterationCount: number; // Number of loop iterations
    startTime: number;     // Epoch timestamp
    endTime: number;       // Epoch timestamp
  };
}

Error Codes

CodeMeaningAction
VALIDATION_ERRORAST validation failedFix the code — blocked construct used
EXECUTION_TIMEOUTExecution exceeded timeoutOptimize or increase timeout
MAX_TOOL_CALLSTool call limit exceededReduce tool calls or increase limit
MAX_ITERATIONSLoop iteration limit exceededReduce loops or increase limit
IFRAME_CREATE_FAILEDFailed to create sandbox iframeCheck browser compatibility
EXECUTION_ABORTEDExecution was manually abortedExpected when calling abort()
ADAPTER_DISPOSEDAdapter was disposed during executionAvoid disposing during execution
ENCLAVE_ERRORUnexpected internal errorCheck error message for details