# vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Package Quality][quality-image]][quality-url] [![Travis CI][travis-image]][travis-url] [![Known Vulnerabilities][snyk-image]][snyk-url]
vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules. Securely!
**Features**
* Runs untrusted code securely in a single process with your code side by side
* Full control over sandbox's console output
* Sandbox has limited access to process's methods
* Sandbox can require modules (builtin and external)
* You can limit access to certain (or all) builtin modules
* You can securely call methods and exchange data and callbacks between sandboxes
* Is immune to all known methods of attacks
* Transpilers support
**How does it work**
* It uses internal VM module to create secure context
* It uses [Proxies](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to prevent escaping the sandbox
* It overrides builtin require to control access to modules
**What is the difference between Node's vm and vm2?**
Try it yourself:
```javascript
const vm = require('vm');
vm.runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');
```
```javascript
const {VM} = require('vm2');
new VM().run('this.constructor.constructor("return process")().exit()');
// Throws ReferenceError: process is not defined
```
## Installation
**IMPORTANT**: Requires Node.js 6 or newer.
npm install vm2
## Quick Example
```javascript
const {VM} = require('vm2');
const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function
```
```javascript
const {NodeVM} = require('vm2');
const vm = new NodeVM({
require: {
external: true
}
});
vm.run(`
var request = require('request');
request('http://www.google.com', function (error, response, body) {
console.error(error);
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
})
`, 'vm.js');
```
## Documentation
* [VM](#vm)
* [NodeVM](#nodevm)
* [VMScript](#vmscript)
* [Error handling](#error-handling)
* [Debugging a sandboxed code](#debugging-a-sandboxed-code)
* [Read-only objects](#read-only-objects-experimental)
* [Protected objects](#protected-objects-experimental)
* [Cross-sandbox relationships](#cross-sandbox-relationships)
* [CLI](#cli)
* [2.x to 3.x changes](https://github.com/patriksimek/vm2/wiki/2.x-to-3.x-changes)
* [1.x and 2.x docs](https://github.com/patriksimek/vm2/wiki/1.x-and-2.x-docs)
* [Contributing](https://github.com/patriksimek/vm2/wiki/Contributing)
## VM
VM is a simple sandbox, without `require` feature, to synchronously run an untrusted code. Only JavaScript built-in objects + Buffer are available. Scheduling functions (`setInterval`, `setTimeout` and `setImmediate`) are not available by default.
**Options:**
* `timeout` - Script timeout in milliseconds.
* `sandbox` - VM's global object.
* `compiler` - `javascript` (default) or `coffeescript` or custom compiler function. The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
* `eval` - If set to `false` any calls to `eval` or function constructors (`Function`, `GeneratorFunction`, etc) will throw an `EvalError` (default: `true`).
* `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`).
* `fixAsync` - If set to `true` any attempt to run code using async will throw a `VMError` (default: `false`).
**IMPORTANT**: Timeout is only effective on synchronous code you run through `run`. Timeout is NOT effective on any method returned by VM. There're some situations when timeout doesn't work - see [#244](https://github.com/patriksimek/vm2/pull/244).
```javascript
const {VM} = require('vm2');
const vm = new VM({
timeout: 1000,
sandbox: {}
});
vm.run("process.exit()"); // throws ReferenceError: process is not defined
```
You can also retrieve values from VM.
```javascript
let number = vm.run("1337"); // returns 1337
```
**TIP**: See tests for more usage examples.
## NodeVM
Unlike `VM`, `NodeVM` lets you require modules same way like in regular Node's context.
**Options:**
* `console` - `inherit` to enable console, `redirect` to redirect to events, `off` to disable console (default: `inherit`).
* `sandbox` - VM's global object.
* `compiler` - `javascript` (default) or `coffeescript` or custom compiler function (which receives the code, and it's filepath). The library expects you to have coffee-script pre-installed if the compiler is set to `coffeescript`.
* `eval` - If set to `false` any calls to `eval` or function constructors (`Function`, `GeneratorFunction`, etc) will throw an `EvalError` (default: `true`).
* `wasm` - If set to `false` any attempt to compile a WebAssembly module will throw a `WebAssembly.CompileError` (default: `true`).
* `sourceExtensions` - Array of file extensions to treat as source code (default: `['js']`).
* `require` - `true` or object to enable `require` method (default: `false`).
* `require.external` - `true`, an array of allowed external modules or an object (default: `false`).
* `require.external.modules` - Array of allowed external modules. Also supports wildcards, so specifying `['@scope/*-ver-??]`, for instance, will allow using all modules having a name of the form `@scope/something-ver-aa`, `@scope/other-ver-11`, etc.
* `require.external.transitive` - Boolean which indicates if transitive dependencies of external modules are allowed (default: `false`).
* `require.builtin` - Array of allowed builtin modules, accepts ["*"] for all (default: none).
* `require.root` - Restricted path(s) where local modules can be required (default: every path).
* `require.mock` - Collection of mock modules (both external or builtin).
* `require.context` - `host` (default) to require modules in host and proxy them to sandbox. `sandbox` to load, compile and require modules in sandbox. Builtin modules except `events` always required in host and proxied to sandbox.
* `require.import` - Array of modules to be loaded into NodeVM on start.
* `require.resolve` - An additional lookup function in case a module wasn't found in one of the traditional node lookup paths.
* `nesting` - `true` to enable VMs nesting (default: `false`).
* `wrapper` - `commonjs` (default) to wrap script into CommonJS wrapper, `none` to retrieve value returned by the script.
* `argv` - Array to be passed to `process.argv`.
* `env` - Object to be passed to `process.env`.
**IMPORTANT**: Timeout is not effective for NodeVM so it is not immune to `while (true) {}` or similar evil.
**REMEMBER**: The more modules you allow, the more fragile your sandbox becomes.
```javascript
const {NodeVM} = require('vm2');
const vm = new NodeVM({
console: 'inherit',
sandbox: {},
require: {
external: true,
builtin: ['fs', 'path'],
root: "./",
mock: {
fs: {
readFileSync() { return 'Nice try!'; }
}
}
}
});
// Sync
let functionInSandbox = vm.run("module.exports = function(who) { console.log('hello '+ who); }");
functionInSandbox('world');
// Async
let functionWithCallbackInSandbox = vm.run("module.exports = function(who, callback) { callback('hello '+ who); }");
functionWithCallbackInSandbox('world', (greeting) => {
console.log(greeting);
});
```
When `wrapper` is set to `none`, `NodeVM` behaves more like `VM` for synchronous code.
```javascript
assert.ok(vm.run('return true') === true);
```
**TIP**: See tests for more usage examples.
### Loading modules by relative path
To load modules by relative path, you must pass full path of the script you're running as a second argument of vm's `run` method if the script is a string. Filename then also shows up in any stack traces produced from t