Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

vm2

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vm2 - npm Package Compare versions

Comparing version 3.0.1 to 3.1.0

CHANGELOG.md

8

lib/cli.js

@@ -8,6 +8,6 @@ const fs = require('fs');

let path = pa.resolve(process.argv[2]);
console.log(`\x1B[90m[vm] creating VM for ${path}\x1B[39m`);
let started = Date.now();
try {

@@ -20,3 +20,3 @@ NodeVM.file(path, {

});
console.log(`\x1B[90m[vm] VM completed in ${Date.now() - started}ms\x1B[39m`);

@@ -28,3 +28,3 @@ } catch (ex) {

let {stack} = ex;
if (stack) {

@@ -31,0 +31,0 @@ console.error(`\x1B[31m[vm:error] ${stack}\x1B[39m`);

@@ -31,6 +31,6 @@ 'use strict'

super(message);
this.name = 'VMError';
this.code = code;
ERROR_CST(this, this.constructor);

@@ -46,6 +46,6 @@ }

proxies: new host.WeakMap(),
arguments: function(args) {
if (!host.Array.isArray(args)) return new host.Array();
let arr = new host.Array();

@@ -62,3 +62,3 @@ for (let i = 0, l = args.length; i < l; i++) arr[i] = Decontextify.value(args[i]);

if (key === '__proto__') return klass.prototype;
try {

@@ -80,3 +80,3 @@ return Decontextify.value(instance[key]);

context = Contextify.value(context);
// Set context of all arguments to vm's context.

@@ -101,3 +101,3 @@ return Decontextify.value(fnc.apply(context, Contextify.arguments(args)));

if (key === '__proto__') return host.Function.prototype;
try {

@@ -113,3 +113,3 @@ return Decontextify.value(fnc[key], deepTraps);

}, traps), deepTraps);
return self;

@@ -125,3 +125,3 @@ },

if (key === '__proto__') return host.Object.prototype;
try {

@@ -147,6 +147,6 @@ return Decontextify.value(object[key], deepTraps);

}
// Following code prevents V8 to throw
// TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '<prop>' which is either non-existant or configurable in the proxy target
if (!def) {

@@ -198,3 +198,3 @@ return undefined;

}, traps));
Decontextify.proxies.set(object, proxy);

@@ -212,3 +212,3 @@ Decontextified.set(proxy, object);

}
switch (typeof value) {

@@ -240,6 +240,6 @@ case 'object':

return Decontextify.function(value, traps, deepTraps, mock);
case 'undefined':
return undefined;
default: // string, number, boolean, symbol

@@ -257,6 +257,6 @@ return value;

proxies: new host.WeakMap(),
arguments: function(args) {
if (!host.Array.isArray(args)) return new Array();
let arr = new Array();

@@ -321,3 +321,3 @@ for (let i = 0, l = args.length; i < l; i++) arr[i] = Contextify.value(args[i]);

}, traps), deepTraps);
return self;

@@ -354,3 +354,3 @@ },

}
// Following code prevents V8 to throw

@@ -418,3 +418,3 @@ // TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property '<prop>' which is either non-existant or configurable in the proxy target

}
switch (typeof value) {

@@ -447,6 +447,6 @@ case 'object':

return Contextify.function(value, traps, deepTraps, mock);
case 'undefined':
return undefined;
default: // string, number, boolean, symbol

@@ -453,0 +453,0 @@ return value;

@@ -18,3 +18,3 @@ const fs = require('fs');

return require('coffee-script').compile(code, {header: false, bare: true});
case 'javascript':

@@ -25,3 +25,3 @@ case 'java-script':

return code;
default:

@@ -34,3 +34,3 @@ throw new VMError(`Unsupported compiler '${compiler}'.`);

* Class VM.
*
*
* @property {Object} options VM options.

@@ -42,10 +42,10 @@ */

* Create VM instance.
*
*
* @param {Object} [options] VM options.
* @return {VM}
*/
constructor(options = {}) {
super();
// defaults

@@ -92,3 +92,3 @@ this.options = {

});
// prepare global sandbox

@@ -99,3 +99,3 @@ if (this.options.sandbox) {

}
for (let name in this.options.sandbox) {

@@ -106,10 +106,10 @@ this._internal.Contextify.globalValue(this.options.sandbox[name], name);

}
/**
* Run the code in VM.
*
*
* @param {String} code Code to run.
* @return {*} Result of executed code.
*/
run(code) {

@@ -124,3 +124,3 @@ if (this.options.compiler !== 'javascript') {

});
try {

@@ -137,6 +137,6 @@ return this._internal.Decontextify.value(script.runInContext(this._context, {

}
/**
* Class NodeVM.
*
*
* @property {Object} module Pointer to main module.

@@ -148,12 +148,12 @@ */

* Create NodeVM instance.
*
*
* Unlike VM, NodeVM lets you use require same way like in regular node.
*
*
* @param {Object} [options] VM options.
* @return {NodeVM}
*/
constructor(options = {}) {
super();
// defaults

@@ -166,3 +166,4 @@ this.options = {

require: options.require != null ? options.require : false,
nesting: options.nesting != null ? options.nesting : false
nesting: options.nesting != null ? options.nesting : false,
wrapper: options.wrapper != null ? options.wrapper : 'commonjs'
};

@@ -217,3 +218,3 @@

})
let closure = vm.runInContext(`(function (vm, host, Contextify, Decontextify, Buffer) { ${sb} \n})`, this._context, {

@@ -233,3 +234,3 @@ filename: `${__dirname}/sandbox.js`,

}
for (let name in this.options.sandbox) {

@@ -239,3 +240,3 @@ this._internal.Contextify.globalValue(this.options.sandbox[name], name);

}
if (this.options.require && this.options.require.import) {

@@ -245,3 +246,3 @@ if (!Array.isArray(this.options.require.import)) {

}
for (let i = 0, l = this.options.require.import.length; i < l; i++) {

@@ -252,7 +253,7 @@ this.require(this.options.require.import[i]);

}
/**
* @deprecated
*/
call(method, ...args) {

@@ -266,3 +267,3 @@ if ('function' === typeof method) {

}
/**

@@ -273,12 +274,12 @@ * Require a module in VM and return it's exports.

*/
require(module) {
return this.run(`module.exports = require('${module}');`, 'vm.js');
}
/**
* Run the code in NodeVM.
*
* Run the code in NodeVM.
*
* First time you run this method, code is executed same way like in node's regular `require` - it's executed with `module`, `require`, `exports`, `__dirname`, `__filename` variables and expect result in `module.exports'.
*
*
* @param {String} code Code to run.

@@ -288,3 +289,3 @@ * @param {String} [filename] Filename that shows up in any stack traces produced from this script.

*/
run(code, filename) {

@@ -298,3 +299,3 @@ if (this.options.compiler !== 'javascript') {

var dirname = pa.dirname(filename);
} else {

@@ -308,3 +309,3 @@ filename = null;

});
let script = new vm.Script(`(function (exports, require, module, __filename, __dirname) { ${code} \n})`, {

@@ -314,3 +315,3 @@ filename: filename || "vm.js",

});
try {

@@ -321,4 +322,4 @@ let closure = script.runInContext(this._context, {

});
closure.call(this._context, module.exports, this._prepareRequire(dirname), module, filename, dirname);
var returned = closure.call(this._context, module.exports, this._prepareRequire(dirname), module, filename, dirname);
} catch (e) {

@@ -328,3 +329,7 @@ throw this._internal.Decontextify.value(e);

return this._internal.Decontextify.value(module.exports);
if (this.options.wrapper === 'commonjs') {
return this._internal.Decontextify.value(module.exports);
} else {
return this._internal.Decontextify.value(returned);
}
}

@@ -334,3 +339,3 @@

* Create NodeVM and run code inside it.
*
*
* @param {String} script Javascript code.

@@ -341,3 +346,3 @@ * @param {String} [filename] File name (used in stack traces only).

*/
static code(script, filename, options) {

@@ -354,3 +359,3 @@ if (filename != null) {

}
if (arguments.length > 3) {

@@ -362,6 +367,6 @@ throw new VMError("Invalid number of arguments.");

}
/**
* Create NodeVM and run script from file inside it.
*
*
* @param {String} [filename] File name (used in stack traces only).

@@ -371,10 +376,10 @@ * @param {Object} [options] VM options.

*/
static file(filename, options) {
filename = pa.resolve(filename);
if (!fs.existsSync(filename)) {
throw new VMError(`Script '${filename}' not found.`);
}
if (fs.statSync(filename).isDirectory()) {

@@ -390,5 +395,5 @@ throw new VMError("Script must be file, got directory.");

* VMError.
*
*
* @param {String} message Error message.
*
*
* @class

@@ -403,3 +408,3 @@ * @extends {Error}

super(message);
this.name = 'VMError';

@@ -406,0 +411,0 @@

@@ -15,3 +15,3 @@ const {Script} = host.require('vm');

'use strict';
const global = this;

@@ -29,3 +29,3 @@

}
module.exports = JSON_PARSE(code);

@@ -35,3 +35,3 @@ },

if (vm.options.require.context === 'sandbox') throw new VMError('Native modules can be required only with context set to \'host\'.');
try {

@@ -54,5 +54,5 @@ module.exports = Contextify.readonly(host.require(filename));

var code = `(function (exports, require, module, __filename, __dirname) { 'use strict'; ${fs.readFileSync(filename, "utf8")} \n});`;
// Precompile script
let script = new Script(code, {
let script = new Script(code, {
filename: filename || "vm.js",

@@ -62,3 +62,3 @@ displayErrors: false

var closure = script.runInContext(global, {
var closure = script.runInContext(global, {
filename: filename || "vm.js",

@@ -68,5 +68,5 @@ displayErrors: false

} catch (ex) {
throw Contextify.value(e);
throw Contextify.value(ex);
}
// run script

@@ -77,3 +77,3 @@ closure(module.exports, module.require, module, filename, dirname);

};
/**

@@ -85,6 +85,6 @@ * Resolve filename.

path = pa.resolve(path);
let exists = fs.existsSync(path);
let isdir = exists ? fs.statSync(path).isDirectory() : false;
// direct file match

@@ -94,9 +94,9 @@ if (exists && !isdir) return path;

// load as file
if (fs.existsSync(`${path}.js`)) return `${path}.js`;
if (fs.existsSync(`${path}.node`)) return `${path}.node`;
if (fs.existsSync(`${path}.json`)) return `${path}.json`;
// load as directory
if (fs.existsSync(`${path}/package.json`)) {

@@ -109,20 +109,20 @@ try {

}
return _resolveFilename(`${path}/${pkg.main}`);
}
if (fs.existsSync(`${path}/index.js`)) return `${path}/index.js`;
if (fs.existsSync(`${path}/index.node`)) return `${path}/index.node`;
return null;
};
/**
* Builtin require.
*/
const _requireBuiltin = function(modulename) {
if (modulename === 'buffer') return ({Buffer});
if (BUILTINS[modulename]) return BUILTINS[modulename].exports; // Only compiled builtins are stored here
if (modulename === 'util') {

@@ -137,3 +137,3 @@ return Contextify.readonly(host.require(modulename), {

}
if (modulename === 'events') {

@@ -144,3 +144,3 @@ try {

});
// setup module scope

@@ -151,6 +151,6 @@ let module = BUILTINS[modulename] = {

};
// run script
script.runInContext(global)(module.exports, module.require, module, host.process);
return module.exports;

@@ -161,10 +161,10 @@ } catch (e) {

}
return Contextify.readonly(host.require(modulename));
};
/**
* Prepare require.
*/
const _prepareRequire = function(current_dirname) {

@@ -176,11 +176,11 @@ const _require = function(modulename) {

if (typeof modulename !== 'string') throw new VMError(`Invalid module name '${modulename}'`, "EINVALIDNAME");
// Mock?
if (vm.options.require.mock && vm.options.require.mock[modulename]) {
return Contextify.readonly(vm.options.require.mock[modulename]);
}
// Builtin?
if (BUILTIN_MODULES[modulename]) {

@@ -202,8 +202,8 @@ if (host.Array.isArray(vm.options.require.builtin)) {

}
return _requireBuiltin(modulename);
}
// External?
if (!vm.options.require.external) throw new VMError(`Access denied to require '${modulename}'`, "EDENIED");

@@ -213,3 +213,3 @@

// Module is relative file, e.g. ./script.js or ../script.js
if (!current_dirname) throw new VMError("You must specify script path to load relative modules.", "ENOPATH");

@@ -220,25 +220,25 @@

// Module is absolute file, e.g. /script.js or //server/script.js or C:\script.js
var filename = _resolveFilename(modulename);
} else {
// Check node_modules in path
if (!current_dirname) throw new VMError("You must specify script path to load relative modules.", "ENOPATH");
let paths = current_dirname.split(pa.sep);
while (paths.length) {
let path = paths.join(pa.sep);
//console.log modulename, "#{path}#{pa.sep}node_modules#{pa.sep}#{modulename}"
var filename = _resolveFilename(`${path}${pa.sep}node_modules${pa.sep}${modulename}`);
if (filename) break;
paths.pop();
}
}
if (!filename) throw new VMError(`Cannot find module '${modulename}'`, "ENOTFOUND");
// return cache whenever possible

@@ -249,3 +249,3 @@ if (CACHE[filename]) return CACHE[filename].exports;

let extname = pa.extname(filename);
if (vm.options.require.root) {

@@ -257,3 +257,3 @@ let requiredPath = pa.resolve(vm.options.require.root);

}
let module = CACHE[filename] = {

@@ -264,5 +264,5 @@ filename,

};
// lookup extensions
if (EXTENSIONS[extname]) {

@@ -272,6 +272,6 @@ EXTENSIONS[extname](module, filename, dirname);

}
throw new VMError(`Failed to load '${modulename}': Unknown type.`, "ELOADFAIL");
};
return _require;

@@ -283,3 +283,3 @@ };

*/
global.setTimeout = function(callback, delay, ...args) {

@@ -289,3 +289,3 @@ let tmr = host.setTimeout(function() {

}, delay);
let local = {

@@ -295,7 +295,7 @@ ref() { return tmr.ref(); },

};
TIMERS.set(local, tmr);
return local;
};
global.setInterval = function(callback, interval, ...args) {

@@ -305,3 +305,3 @@ let tmr = host.setInterval(function() {

}, interval);
let local = {

@@ -311,7 +311,7 @@ ref() { return tmr.ref(); },

};
TIMERS.set(local, tmr);
return local;
};
global.setImmediate = function(callback, ...args) {

@@ -321,3 +321,3 @@ let tmr = host.setImmediate(function() {

});
let local = {

@@ -327,7 +327,7 @@ ref() { return tmr.ref(); },

};
TIMERS.set(local, tmr);
return local;
};
global.clearTimeout = function(local) {

@@ -337,3 +337,3 @@ host.clearTimeout(TIMERS.get(local));

};
global.clearInterval = function(local) {

@@ -343,3 +343,3 @@ host.clearInterval(TIMERS.get(local));

};
global.clearImmediate = function(local) {

@@ -349,3 +349,3 @@ host.clearImmediate(TIMERS.get(local));

};
global.process = {

@@ -368,7 +368,7 @@ argv: [],

}
host.process.on(name, Decontextify.value(handler));
return this;
},
once(name, handler) {

@@ -382,7 +382,7 @@ if (name !== 'beforeExit' && name !== 'exit') {

},
listeners(name) {
return Contextify.readonly(host.process.listeners(name));
},
removeListener(name, handler) {

@@ -392,3 +392,3 @@ host.process.removeListener(name, Decontextify.value(handler));

},
umask() {

@@ -398,7 +398,7 @@ if (arguments.length) {

}
return host.process.umask();
}
};
if (vm.options.console === 'inherit') {

@@ -411,3 +411,3 @@ global.console = Contextify.readonly(host.console);

return null;
},
},
info(...args) {

@@ -414,0 +414,0 @@ vm.emit('console.info', ...Decontextify.arguments(args));

@@ -16,3 +16,3 @@ {

],
"version": "3.0.1",
"version": "3.1.0",
"main": "index.js",

@@ -19,0 +19,0 @@ "repository": {

@@ -73,3 +73,3 @@ # vm2 [![NPM Version][npm-image]][npm-url] [![Package Quality][quality-image]][quality-url] [![Travis CI][travis-image]][travis-url]

* `timeout` - Script timeout in milliseconds.
* `timeout` - Script timeout in milliseconds.
* `sandbox` - VM's global object.

@@ -116,2 +116,3 @@ * `compiler` - `javascript` (default) or `coffeescript` or custom compiler function.

* `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.

@@ -144,2 +145,8 @@ **IMPORTANT**: Timeout is not effective for NodeVM so it is not immune to `while (true) {}` or similar evil.

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.

@@ -146,0 +153,0 @@

@@ -1,1 +0,1 @@

{"working": true}
{"working": true}

@@ -8,3 +8,3 @@ const assert = require("assert");

let vm;
class TestClass {

@@ -50,3 +50,3 @@ constructor() {

}
before(done => {

@@ -56,3 +56,3 @@ vm = new VM({sandbox});

})
it('common', done => {

@@ -70,3 +70,3 @@ assert.ok(vm.run(`global.__proto__ === Object.prototype`));

assert.ok(vm.run(`Array.prototype.__proto__ === Object.prototype`));
assert.strictEqual(sandbox.test.object.y === sandbox.test.object.y.valueOf(), true);

@@ -91,3 +91,3 @@ assert.strictEqual(vm.run("test.object.y instanceof Function"), true);

assert.strictEqual(vm.run("test.object.valueOf().y.constructor('return (function(){return this})().isVM')()"), true);
let o = vm.run("let x = {a: test.date, b: test.date};x");

@@ -100,3 +100,3 @@ assert.strictEqual(vm.run("x.valueOf().a instanceof Date"), true);

assert.strictEqual(o.a === sandbox.test.date, true);
o = vm.run("let y = new Date(); let z = {a: y, b: y};z");

@@ -108,6 +108,6 @@ assert.strictEqual(o.isVMProxy, true);

assert.strictEqual(o.a === o.b, true);
done();
})
it('class', done => {

@@ -117,27 +117,27 @@ assert.strictEqual(vm.run("new test.klass()").isVMProxy, undefined);

assert.strictEqual(vm.run("new test.klass()") instanceof TestClass, true);
//vm.run("class LocalClass extends test.klass {}");
done();
})
it('string', done => {
assert.strictEqual(vm.run("(test.string).constructor === String"), true);
assert.strictEqual(vm.run("typeof(test.stringO) === 'string' && test.string.valueOf instanceof Object"), true);
done();
})
it('number', done => {
assert.strictEqual(vm.run("typeof(test.numberO) === 'number' && test.number.valueOf instanceof Object"), true);
done();
})
it('boolean', done => {
assert.strictEqual(vm.run("typeof(test.booleanO) === 'boolean' && test.boolean.valueOf instanceof Object"), true);
done();
})
it('date', done => {

@@ -147,12 +147,12 @@ assert.strictEqual(vm.run("test.date instanceof Date"), true);

assert.strictEqual(vm.run("test.date"), sandbox.test.date);
done();
})
it('regexp', done => {
assert.strictEqual(vm.run("test.regexp instanceof RegExp"), true);
done();
})
it('buffer', done => {

@@ -164,3 +164,3 @@ assert.strictEqual(vm.run("test.buffer.inspect()"), '<Buffer 00 01>', '#1');

assert.strictEqual(vm.run("class Buffer2 extends Buffer {};new Buffer2(5)").fill(1).inspect(), '<Buffer 01 01 01 01 01>');
let {a, b, c, d} = vm.run(`

@@ -184,6 +184,6 @@ let a = new Buffer([0x01, 0x02]);

assert.ok(d.constructor.constructor === Function, '#12');
({a: a, b: b, c: c, d: d})
`);
assert.ok(a instanceof Buffer);

@@ -201,6 +201,6 @@ assert.ok(b instanceof Buffer);

assert.ok(d.constructor.constructor === Function);
done();
})
it('function', done => {

@@ -210,6 +210,6 @@ assert.strictEqual(vm.run("test.function instanceof Function"), true, '#1');

assert.strictEqual(vm.run("test.function()() instanceof Object"), true, '#3');
done();
})
it('object', done => {

@@ -223,18 +223,18 @@ assert.strictEqual(vm.run("test.object instanceof Object && test.object.x === 1"), true, '#1');

assert.strictEqual(vm.run("Object.getOwnPropertyDescriptor(test.object, 'y').hasOwnProperty.constructor('return (function(){return this})().isVM')()"), true, '#7');
done();
})
it('null', done => {
assert.strictEqual(vm.run("test.nil === null"), true);
done();
})
it('undefined', done => {
assert.strictEqual(vm.run("test.undef === undefined"), true);
done();
})
it('symbol', done => {

@@ -248,6 +248,6 @@ assert.strictEqual(vm.run("Symbol.for('foo') === test.symbol2"), true);

assert.strictEqual(vm.run("Symbol.keyFor(test.symbol2)"), 'foo');
done();
})
it('error', done => {

@@ -261,3 +261,3 @@ assert.strictEqual(vm.run("Object.getOwnPropertyDescriptor(test.error, 'stack').get.constructor === Function;"), true);

vm = null;
done();

@@ -269,3 +269,3 @@ })

let vm;
before(done => {

@@ -276,3 +276,3 @@ let sandbox = {

}
Object.defineProperty(sandbox.sub, 'getter', {

@@ -288,3 +288,3 @@ get() {

})
vm = new VM({

@@ -294,12 +294,12 @@ timeout: 10,

})
done();
})
it('globals', done => {
assert.equal(vm.run("round(1.5)"), 2);
done();
})
it('errors', done => {

@@ -312,6 +312,6 @@ assert.throws(() => vm.run("notdefined"), /notdefined is not defined/);

})
done();
})
it('timeout', done => {

@@ -322,6 +322,6 @@ assert.throws(() => new VM({

assert.throws(() => vm.run("sub.getter"), /Script execution timed out\./);
done();
})
it('timers', done => {

@@ -331,11 +331,11 @@ assert.equal(vm.run("global.setTimeout"), void 0);

assert.equal(vm.run("global.setImmediate"), void 0);
done();
})
it('various attacks #1', done => {
let vm2 = new VM({sandbox: {log: console.log, boom: function() { throw new Error(); }}});
assert.strictEqual(vm2.run("this.constructor.constructor('return Function(\\'return Function\\')')()() === this.constructor.constructor('return Function')()"), true);
assert.throws(() => vm2.run(`

@@ -360,3 +360,3 @@ const ForeignFunction = global.constructor.constructor;

}
Reflect.construct = exploit;

@@ -371,3 +371,3 @@ new Buffer([0]);

`), '#4');
assert.doesNotThrow(() => vm2.run(`

@@ -378,3 +378,3 @@ global.String = function(text) {

`)('asdf'), '#5');
assert.doesNotThrow(() => vm2.run(`

@@ -385,3 +385,3 @@ global.String = function(text) {

`)(new String('asdf')), '#6');
assert.doesNotThrow(() => vm2.run(`

@@ -395,3 +395,3 @@ global.Buffer = function(value) {

})
it('various attacks #2', done => {

@@ -404,3 +404,3 @@ let vm2 = new VM({

});
assert.doesNotThrow(() => vm2.run(`

@@ -412,3 +412,3 @@ Object.assign = function (o) {

`), '#1');
assert.doesNotThrow(() => vm2.run(`

@@ -421,3 +421,3 @@ try {

`), '#2');
assert.doesNotThrow(() => vm2.run(`

@@ -432,3 +432,3 @@ let o;

`), '#3');
assert.doesNotThrow(() => vm2.run(`

@@ -444,3 +444,3 @@ let method = () => {};

`)('asdf'), '#4');
assert.doesNotThrow(() => vm2.run(`

@@ -454,3 +454,3 @@ let proxy2 = new Proxy(function() {}, {

`)('asdf'), '#5');
assert.strictEqual(vm2.run(`

@@ -460,11 +460,11 @@ global.DEBUG = true;

`), undefined, '#6');
assert.throws(() => vm2.run(`
global.constructor.constructor('return this')().constructor.constructor('return process')()
`), /process is not defined/, '#7');
assert.throws(() => vm2.run(`
global.__proto__.constructor.constructor('return this')().constructor.constructor('return process')()
`), /process is not defined/, '#8');
assert.doesNotThrow(() => vm2.run(`

@@ -480,3 +480,3 @@ if (!(Object.keys(boom) instanceof Array)) throw new Error('Shouldnt be there.');

vm = null;
done();

@@ -488,9 +488,9 @@ })

let vm;
before(done => {
vm = new NodeVM;
done();
})
it('globals', done => {

@@ -500,31 +500,31 @@ let ex;

assert.equal(ex.isVM, true);
done();
})
it('errors', done => {
assert.throws(() => vm.run("notdefined"), /notdefined is not defined/);
done();
})
it('prevent global access', done => {
assert.throws(() => vm.run("process.exit()"), /(undefined is not a function|process\.exit is not a function)/);
done();
})
it('arguments attack', done => {
assert.strictEqual(vm.run("module.exports = (function() { return arguments.callee.caller.constructor === Function; })()"), true);
assert.throws(() => vm.run("module.exports = (function() { return arguments.callee.caller.caller.toString(); })()"), /Cannot read property 'toString' of null/);
done();
})
it('global attack', done => {
assert.equal(vm.run("module.exports = console.log.constructor('return (function(){return this})().isVM')()"), true);
done();
})
it.skip('timeout (not supported by Node\'s VM)', done => {

@@ -534,9 +534,9 @@ assert.throws(() => new NodeVM({

}).run("while (true) {}"), /Script execution timed out\./);
done();
})
after(done => {
vm = null;
done();

@@ -553,8 +553,8 @@ })

})
assert.equal(vm.run(`module.exports = require('${__dirname}/data/json.json')`).working, true);
done();
})
it.skip('run coffee-script', done => {

@@ -567,16 +567,16 @@ let vm = new NodeVM({

})
assert.equal(vm.run("module.exports = working: true").working, true);
done();
})
it('disabled require', done => {
let vm = new NodeVM;
assert.throws(() => vm.run("require('fs')"), /Access denied to require 'fs'/);
done();
})
it('disable setters on builtin modules', done => {

@@ -588,9 +588,9 @@ let vm = new NodeVM({

})
vm.run("require('fs').readFileSync = undefined");
assert.strictEqual(require('fs').readFileSync instanceof Function, true);
vm.run("require('fs').readFileSync.thisPropertyShouldntBeThere = true");
assert.strictEqual(require('fs').readFileSync.thisPropertyShouldntBeThere, undefined);
assert.throws(() => vm.run("Object.defineProperty(require('fs'), 'test', {})"), err => {

@@ -602,3 +602,3 @@ assert.ok(err instanceof TypeError);

})
assert.throws(() => vm.run("'use strict'; delete require('fs').readFileSync"), err => {

@@ -610,6 +610,6 @@ assert.ok(err instanceof TypeError);

})
done();
})
it('enabled require for certain modules', done => {

@@ -621,8 +621,8 @@ let vm = new NodeVM({

})
assert.doesNotThrow(() => vm.run("require('fs')"));
done();
})
it('require relative', done => {

@@ -634,20 +634,20 @@ let vm = new NodeVM({

})
vm.run("require('foobar')", __filename);
done();
})
it('arguments attack', done => {
let vm = new NodeVM;
assert.throws(() => vm.run("module.exports = function fce(msg) { return arguments.callee.caller.toString(); }")(), /Cannot read property 'toString' of null/);
vm = new NodeVM;
assert.throws(() => vm.run("module.exports = function fce(msg) { return fce.caller.toString(); }")(), /Cannot read property 'toString' of null/);
done();
})
it('builtin module arguments attack', done => {

@@ -663,6 +663,6 @@ let vm = new NodeVM({

})
vm.run("var fs = require('fs'); fs.exists(parentfilename, function() {try {arguments.callee.caller.toString()} catch (err) {return done();}; done(new Error('Missing expected exception'))})");
})
it('path attack', done => {

@@ -675,8 +675,8 @@ let vm = new NodeVM({

})
assert.throws(() => vm.run("var test = require('../package.json')", __filename), /Module '\.\.\/package.json' is not allowed to be required\. The path is outside the border!/);
done();
})
it('process events', done => {

@@ -688,3 +688,3 @@ let vm = new NodeVM({

})
let sandbox = vm.run("global.VM2_HANDLER = function() { VM2_COUNTER++ }; process.on('exit', VM2_HANDLER); module.exports = global;");

@@ -697,6 +697,6 @@ process.emit('exit');

assert.strictEqual(sandbox.VM2_COUNTER, 1);
done();
})
it('timers', done => {

@@ -708,5 +708,5 @@ let vm = new NodeVM({

})
vm.run('let i = setImmediate(function() { global.TICK = true; });clearImmediate(i);');
setImmediate(() => {

@@ -717,3 +717,3 @@ assert.strictEqual(vm.run('module.exports = global.TICK'), void 0);

})
it('mock', done => {

@@ -729,6 +729,6 @@ let vm = new NodeVM({

})
assert.strictEqual(vm.run("module.exports = require('fs').constructor.constructor === Function"), true);
assert.strictEqual(vm.run("module.exports = require('fs').readFileSync()"), 'Nice try!');
done();

@@ -743,3 +743,3 @@ })

})
let nestedObject = vm.run(`

@@ -751,7 +751,19 @@ const {VM} = require('vm2');

`, 'vm.js');
assert.strictEqual(nestedObject.constructor.constructor === Function, true);
done();
})
})
describe('wrappers', () => {
it('none', done => {
let vm = new NodeVM({
wrapper: 'none'
})
assert.strictEqual(vm.run('return 2 + 2'), 4)
done()
})
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc