UNPKG

@mariozechner/jailjs

Version:

Lightweight JavaScript interpreter for isolated execution. For plugins, user scripts, and browser extensions. Not for adversarial code - use SandboxJS or isolated-vm for that.

186 lines (134 loc) 5.09 kB
# JailJS JavaScript AST interpreter for **isolated execution** in browsers and Node.js. **Use cases**: Plugin systems, user scripts, controlled execution environments **Not for**: Security sandboxing of untrusted code [Read the "behind the scenes" blog post](https://mariozechner.at/posts/2025-10-05-jailjs/) ## Features - **Complete ES5 Support**: Full implementation of all ES5 language features - **ES6+ Transformation**: Optional Babel-based transform to ES5 AST - **Scope Isolation**: Custom global environment, blocks `constructor`/`__proto__` on built-ins - **Tree-shakeable**: Separate parser (~300 KB) from interpreter (~10 KB) - **Universal**: Works in browsers and Node.js ## Installation ```bash npm install @mariozechner/jailjs ``` ## Quick Start ```typescript import { Interpreter, parse } from '@mariozechner/jailjs'; const interpreter = new Interpreter(); const result = interpreter.evaluate(parse('2 + 2')); console.log(result); // 4 ``` ## Examples - **[web](example/web)** - Browser playground with ES6+ examples and security demos - **[node](example/node)** - CLI demo with eval() and timeout protection - **[chrome-extension](example/chrome-extension)** - Manifest V3 extension with user scripts ## API ### Basic Usage ```typescript import { Interpreter, parse } from '@mariozechner/jailjs'; // With custom globals const interpreter = new Interpreter({ console: { log: (...args) => console.log('[Sandbox]', ...args) }, myAPI: { getData: () => fetchData() } }, { maxOps: 100000 // Operation limit for timeout protection (optional) }); const ast = parse('myAPI.getData()'); const result = interpreter.evaluate(ast); ``` ### ES6+ Transformation ```typescript import { Interpreter } from '@mariozechner/jailjs'; import { transformToES5 } from '@mariozechner/jailjs/transform'; const code = ` const double = (x) => x * 2; [1, 2, 3].map(double); `; const ast = transformToES5(code); const result = new Interpreter().evaluate(ast); console.log(result); // [2, 4, 6] ``` Supports: arrow functions, classes, template literals, destructuring, spread operators, async/await, TypeScript, JSX. **Top-level await:** Wrap code in an async IIFE: ```typescript const code = ` (async () => { await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Done!'); })(); `; ``` ### Tree-shaking Parse ahead-of-time to bundle only the interpreter (~10 KB): ```typescript // Build-time import { parse } from '@mariozechner/jailjs/parser'; const ast = parse(userScript); fs.writeFileSync('script.ast.json', JSON.stringify(ast)); // Runtime (bundle only interpreter) import { Interpreter } from '@mariozechner/jailjs'; const ast = JSON.parse(fs.readFileSync('script.ast.json')); new Interpreter().evaluate(ast); ``` ## Default Globals ```typescript // Built-ins console, Math, JSON, Date, RegExp // Constructors (prototypes can be polluted!) Array, Object, String, Number, Boolean // ES6+ (for transformed code) Symbol, Promise // Errors Error, TypeError, ReferenceError, SyntaxError, RangeError, EvalError, URIError // Global functions parseInt, parseFloat, isNaN, isFinite encodeURI, encodeURIComponent, decodeURI, decodeURIComponent // Blocked Function: undefined // Blocked to prevent eval-like behavior eval: undefined // Disabled unless you provide parser via options ``` ## Security ⚠️ **JailJS is NOT a security sandbox**. It provides scope isolation for controlled environments, but: - ❌ Prototype pollution is possible (`Array.prototype`, `Object.prototype`) - ❌ No prototype method allowlisting - ❌ Many escape vectors exist - ❌ No memory or execution time limits (only basic operation counter) **What is blocked**: - `[].constructor``undefined` (on built-in types) - `obj.__proto__``undefined` - `Function()``undefined` - Global scope (`window`, `globalThis`, etc.) **For untrusted code**, use: - [SandboxJS](https://github.com/nyariv/SandboxJS) - Prototype whitelisting and comprehensive security - [isolated-vm](https://github.com/laverdet/isolated-vm) - V8 isolates for Node.js - Web Workers or separate processes JailJS gives you **tools to build isolation** (custom globals, operation limits, AST interpretation), but **cannot guarantee security**. You are responsible for validating use cases and layering additional protections. ## Supported Features ### ES5 (Native) - ✅ All operators, control flow, functions, closures - ✅ Objects, arrays, prototypes, `this` binding -`try`/`catch`/`finally`, error handling - ✅ Variable hoisting, `arguments` ### ES6+ (via Transform) - ✅ Classes, arrow functions, template literals -`let`/`const`, destructuring, spread - ✅ Async/await, promises - ✅ TypeScript, JSX (optional) ### Not Supported - ❌ Generators (WIP) - ❌ ES6 modules - ❌ Proxies, Reflect, WeakRef - ❌ SharedArrayBuffer, Atomics ## Performance ~10-100x slower than native JavaScript. Use `maxOps` for timeout protection. ## Development ```bash npm install npm run build npm test npm run dev # Watch mode ``` ## License MIT