@enclave-vm/browser implements defense-in-depth through a double iframe architecture. Each execution creates two nested iframes — an outer security barrier and an inner sandbox — with 8 distinct security layers that work together to prevent sandbox escapes.
Double Iframe Architecture
- Host Page: Your application. Creates the outer iframe and handles tool calls.
- Outer Iframe: Security barrier with rate limiting, pattern detection, and name filtering. Relays validated messages between host and inner iframe.
- Inner Iframe: The actual sandbox. Contains prototype hardening, secure proxies, safe runtime wrappers, and the user code.
The 8 Security Layers
Layer 1: Content Security Policy
Both iframes are created with a strict CSP via<meta> tag:
Layer 2: Iframe Sandbox Attribute
Both iframes use a restrictive sandbox attribute:allow-scripts is enabled. Crucially, allow-same-origin is not set, which means:
- The iframe cannot access the host page’s DOM, cookies, or storage
- The iframe cannot read
parent.documentortop.document - The iframe has a unique
nullorigin
Layer 3: Outer Frame Validation
The outer iframe acts as a security barrier between the host and the inner sandbox. All tool calls from the inner iframe pass through validation:Layer 4: Dangerous Global Removal
Dangerous globals are deleted from the inner iframe’swindow object based on the security level:
Always removed (all security levels):
fetch, XMLHttpRequest, WebSocket, EventSource, Worker, SharedWorker, ServiceWorker, importScripts, localStorage, sessionStorage, indexedDB, caches, navigator, open, close, alert, confirm, prompt, document
Layer 5: Prototype Freezing
All built-in prototypes are frozen after security patches are applied:Object.prototype,Array.prototype,Function.prototypeString.prototype,Number.prototype,Boolean.prototypeDate.prototype,Error.prototype,Promise.prototypeTypeError.prototype,RangeError.prototype,SyntaxError.prototypeReferenceError.prototype,URIError.prototype,EvalError.prototype
__lookupGetter__, __lookupSetter__, __defineGetter__, __defineSetter__) are replaced with no-ops on Object.prototype. Error prototypes have __proto__ shadowed to return null.
Layer 6: Secure Proxy
Every global object exposed to user code is wrapped in aProxy that blocks access to dangerous properties:
The proxy behavior is configurable per security level. At
STRICT and SECURE levels, accessing blocked properties throws an error. At PERMISSIVE, it returns undefined.
Additionally, dangerous static methods on Object are neutralized: defineProperty, defineProperties, setPrototypeOf, getOwnPropertyDescriptor, and getOwnPropertyDescriptors.
Layer 7: Safe Runtime Wrappers
User code runs through transformed wrappers that enforce resource limits:
All loop wrappers share a global iteration counter and check for abort signals on every iteration.
Layer 8: Memory Tracking
Memory-intensive operations are patched to track estimated usage:
When the cumulative tracked memory exceeds
memoryLimit (default: 1MB), a RangeError is thrown.
Message Protocol
All communication between layers usespostMessage with validated messages. Every message includes a __enclave_msg__: true discriminator and a requestId for correlation.
Message Types
All messages are validated with Zod schemas. Tool names must match
^[a-zA-Z][a-zA-Z0-9:_-]*$ and be 1–256 characters.
What’s Blocked
What’s Available
Sandboxed code has access to a safe subset of JavaScript:Related
- Overview - Getting started with browser enclave
- Configuration - All configuration options
- Double VM Layer - Node.js equivalent architecture
- Security Levels - Security preset details