Lightweight JavaScript interpreter for isolated execution. For plugins, user scripts, and browser extensions. Not for adversarial code - use SandboxJS or isolated-vm for that.
npm install @mariozechner/jailjsJavaScript 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
- 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
``bash`
npm install @mariozechner/jailjs
`typescript
import { Interpreter, parse } from '@mariozechner/jailjs';
const interpreter = new Interpreter();
const result = interpreter.evaluate(parse('2 + 2'));
console.log(result); // 4
`
- web - Browser playground with ES6+ examples and security demos
- node - CLI demo with eval() and timeout protection
- chrome-extension - Manifest V3 extension with user scripts
`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);
`
`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!');
})();;`
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);
`
`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
`
⚠️ 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__
- → undefinedFunction()
- → undefinedwindow
- Global scope (, globalThis, etc.)
For untrusted code, use:
- SandboxJS - Prototype whitelisting and comprehensive security
- 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.
binding
- ✅ try/catch/finally, error handling
- ✅ Variable hoisting, arguments$3
- ✅ Classes, arrow functions, template literals
- ✅ let/const, destructuring, spread
- ✅ Async/await, promises
- ✅ TypeScript, JSX (optional)$3
- ❌ Generators (WIP)
- ❌ ES6 modules
- ❌ Proxies, Reflect, WeakRef
- ❌ SharedArrayBuffer, AtomicsPerformance
~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
``MIT