Gathering detailed insights and metrics for @takeshape/vm2
Gathering detailed insights and metrics for @takeshape/vm2
Gathering detailed insights and metrics for @takeshape/vm2
Gathering detailed insights and metrics for @takeshape/vm2
npm install @takeshape/vm2
Typescript
Module System
Min. Node Version
Node Version
NPM Version
JavaScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
369 Commits
1 Watchers
6 Branches
4 Contributors
Updated on Feb 07, 2022
Latest Version
3.9.5
Package Id
@takeshape/vm2@3.9.5
Unpacked Size
124.93 kB
Size
26.85 kB
File Count
9
NPM Version
6.14.15
Node Version
14.18.2
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
4
vm2 is a sandbox that can run untrusted code with whitelisted Node's built-in modules. Securely!
Features
How does it work
What is the difference between Node's vm and vm2?
Try it yourself:
1const vm = require('vm'); 2vm.runInNewContext('this.constructor.constructor("return process")().exit()'); 3console.log('Never gets executed.');
1const {VM} = require('@takeshape/vm2'); 2new VM().run('this.constructor.constructor("return process")().exit()'); 3// Throws ReferenceError: process is not defined
IMPORTANT: Requires Node.js 6 or newer.
npm install vm2
1const {VM} = require('@takeshape/vm2'); 2const vm = new VM(); 3 4vm.run(`process.exit()`); // TypeError: process.exit is not a function
1const {NodeVM} = require('@takeshape/vm2'); 2const vm = new NodeVM({ 3 require: { 4 external: true 5 } 6}); 7 8vm.run(` 9 var request = require('request'); 10 request('http://www.google.com', function (error, response, body) { 11 console.error(error); 12 if (!error && response.statusCode == 200) { 13 console.log(body) // Show the HTML for the Google homepage. 14 } 15 }) 16`, 'vm.js');
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.
1const {VM} = require('@takeshape/vm2'); 2 3const vm = new VM({ 4 timeout: 1000, 5 sandbox: {} 6}); 7 8vm.run("process.exit()"); // throws ReferenceError: process is not defined
You can also retrieve values from VM.
1let number = vm.run("1337"); // returns 1337
TIP: See tests for more usage examples.
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
.strict
- true
to loaded modules in strict mode (default: false
).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.
1const {NodeVM} = require('@takeshape/vm2'); 2 3const vm = new NodeVM({ 4 console: 'inherit', 5 sandbox: {}, 6 require: { 7 external: true, 8 builtin: ['fs', 'path'], 9 root: "./", 10 mock: { 11 fs: { 12 readFileSync() { return 'Nice try!'; } 13 } 14 } 15 } 16}); 17 18// Sync 19 20let functionInSandbox = vm.run("module.exports = function(who) { console.log('hello '+ who); }"); 21functionInSandbox('world'); 22 23// Async 24 25let functionWithCallbackInSandbox = vm.run("module.exports = function(who, callback) { callback('hello '+ who); }"); 26functionWithCallbackInSandbox('world', (greeting) => { 27 console.log(greeting); 28});
When wrapper
is set to none
, NodeVM
behaves more like VM
for synchronous code.
1assert.ok(vm.run('return true') === true);
TIP: See tests for more usage examples.
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 the script.
1vm.run("require('foobar')", "/data/myvmscript.js");
If the script you are running is an VMScript, the path is given in the VMScript constructor.
1const script = new VMScript("require('foobar')", {filename: "/data/myvmscript.js"}); 2vm.run(script);
You can increase performance by using pre-compiled scripts. The pre-compiled VMScript can be run later multiple times. It is important to note that the code is not bound to any VM (context); rather, it is bound before each run, just for that run.
1const {VM, VMScript} = require('@takeshape/vm2'); 2 3const vm = new VM(); 4const script = new VMScript("Math.random()"); 5console.log(vm.run(script)); 6console.log(vm.run(script));
Works for both VM
and NodeVM
.
1const {NodeVM, VMScript} = require('@takeshape/vm2'); 2 3const vm = new NodeVM(); 4const script = new VMScript("module.exports = Math.random()"); 5console.log(vm.run(script)); 6console.log(vm.run(script));
Code is compiled automatically first time you run it. You can compile the code anytime with script.compile()
. Once the code is compiled, the method has no effect.
Errors in code compilation and synchronous code execution can be handled by try
/catch
. Errors in asynchronous code execution can be handled by attaching uncaughtException
event handler to Node's process
.
1try { 2 var script = new VMScript("Math.random()").compile(); 3} catch (err) { 4 console.error('Failed to compile script.', err); 5} 6 7try { 8 vm.run(script); 9} catch (err) { 10 console.error('Failed to execute script.', err); 11} 12 13process.on('uncaughtException', (err) => { 14 console.error('Asynchronous error caught.', err); 15})
You can debug/inspect code running in the sandbox as if it was running in a normal process.
debugger
keyword.Example
/tmp/main.js:
1const {VM, VMScript} = require('.'); 2const fs = require('fs'); 3const file = `${__dirname}/sandbox.js`; 4 5// By providing a file name as second argument you enable breakpoints 6const script = new VMScript(fs.readFileSync(file), file); 7 8new VM().run(script);
/tmp/sandbox.js
1const foo = 'ahoj'; 2 3// Debugger keyword works just fine anywhere. 4// Even without specifying a file name to the VMScript object. 5debugger;
To prevent sandboxed script to add/change/delete properties to/from the proxied objects, you can use freeze
methods to make the object read-only. This is only effective inside VM. Frozen objects are affected deeply. Primitive types can not be frozen.
Example without using freeze
:
1const util = { 2 add: (a, b) => a + b 3} 4 5const vm = new VM({ 6 sandbox: {util} 7}); 8 9vm.run('util.add = (a, b) => a - b'); 10console.log(util.add(1, 1)); // returns 0
Example with using freeze
:
1const vm = new VM(); // Objects specified in sandbox can not be frozen. 2vm.freeze(util, 'util'); // Second argument adds object to global. 3 4vm.run('util.add = (a, b) => a - b'); // Fails silently when not in strict mode. 5console.log(util.add(1, 1)); // returns 2
IMPORTANT: It is not possible to freeze objects that has already been proxied to the VM.
Unlike freeze
, this method allows sandboxed script to add/modify/delete properties on object with one exception - it is not possible to attach functions. Sandboxed script is therefore not able to modify methods like toJSON
, toString
or inspect
.
IMPORTANT: It is not possible to protect objects that has already been proxied to the VM.
1const assert = require('assert'); 2const {VM} = require('@takeshape/vm2'); 3 4const sandbox = { 5 object: new Object(), 6 func: new Function(), 7 buffer: new Buffer([0x01, 0x05]) 8} 9 10const vm = new VM({sandbox}); 11 12assert.ok(vm.run(`object`) === sandbox.object); 13assert.ok(vm.run(`object instanceof Object`)); 14assert.ok(vm.run(`object`) instanceof Object); 15assert.ok(vm.run(`object.__proto__ === Object.prototype`)); 16assert.ok(vm.run(`object`).__proto__ === Object.prototype); 17 18assert.ok(vm.run(`func`) === sandbox.func); 19assert.ok(vm.run(`func instanceof Function`)); 20assert.ok(vm.run(`func`) instanceof Function); 21assert.ok(vm.run(`func.__proto__ === Function.prototype`)); 22assert.ok(vm.run(`func`).__proto__ === Function.prototype); 23 24assert.ok(vm.run(`new func() instanceof func`)); 25assert.ok(vm.run(`new func()`) instanceof sandbox.func); 26assert.ok(vm.run(`new func().__proto__ === func.prototype`)); 27assert.ok(vm.run(`new func()`).__proto__ === sandbox.func.prototype); 28 29assert.ok(vm.run(`buffer`) === sandbox.buffer); 30assert.ok(vm.run(`buffer instanceof Buffer`)); 31assert.ok(vm.run(`buffer`) instanceof Buffer); 32assert.ok(vm.run(`buffer.__proto__ === Buffer.prototype`)); 33assert.ok(vm.run(`buffer`).__proto__ === Buffer.prototype); 34assert.ok(vm.run(`buffer.slice(0, 1) instanceof Buffer`)); 35assert.ok(vm.run(`buffer.slice(0, 1)`) instanceof Buffer);
Before you can use vm2 in command line, install it globally with npm install vm2 -g
.
$ vm2 ./script.js
package.json
version numbernpm publish
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 1
Details
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no SAST tool detected
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
14 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More