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.3.1 to 3.4.0

6

CHANGELOG.md

@@ -0,4 +1,8 @@

v3.4.0 (2017-03-28)
-------------------
[new] Added experimental VM.protect method
v3.3.1 (2017-03-27)
-------------------
[new] Added support for freezing objects
[new] Added VM.freeze method

@@ -5,0 +9,0 @@ v3.2.0 (2017-02-10)

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

get: (target, key) => _freeze(object[key]),
set: (target, key) => { throw new Error('Object is read-only.') },
setPrototypeOf: (target, key) => { throw new Error('Object is read-only.') },
defineProperty: (target, key) => { throw new Error('Object is read-only.') },
deleteProperty: (target, key) => { throw new Error('Object is read-only.') },
set: (target, key) => { throw new VMError('Object is read-only.') },
setPrototypeOf: (target, key) => { throw new VMError('Object is read-only.') },
defineProperty: (target, key) => { throw new VMError('Object is read-only.') },
deleteProperty: (target, key) => { throw new VMError('Object is read-only.') },
isExtensible: (target, key) => false,
preventExtensions: (target) => { throw new Error('Object is read-only.') }
preventExtensions: (target) => { throw new VMError('Object is read-only.') }
});

@@ -47,2 +47,21 @@ }

const _protect = function protect(object) {
if (typeof object === 'object' || typeof object === 'function') {
return new Proxy(object, {
get: (target, key) => _protect(object[key]),
set: (target, key, value) => {
if (typeof value === 'function') throw new VMError('Assigning a function to protected object is prohibited.');
object[key] = value
},
setPrototypeOf: (target, key) => { throw new VMError('Changing prototype on protected object is prohibited.') },
defineProperty: (target, key) => { throw new VMError('Defining property on protected object is prohibited.') },
deleteProperty: (target, key) => delete object[key],
isExtensible: (target, key) => false,
preventExtensions: (target) => { throw new VMError('Method is prohibited on protected object.') }
});
}
return object;
}
/**

@@ -107,7 +126,7 @@ * Class Script

/**
* Makes the value read only.
* Makes the object read only.
*
* @static
* @param {*} value Value to freeze.
* @return {*} Frozen value.
* @param {*} object Object to freeze.
* @return {*} Frozen object.
*/

@@ -120,2 +139,14 @@

/**
* Protects the object.
*
* @static
* @param {*} object Object to protect.
* @return {*} Protected object.
*/
static protect(object) {
return _protect(object);
}
/**
* Create VM instance.

@@ -220,7 +251,7 @@ *

/**
* Makes the value read only.
* Makes the object read only.
*
* @static
* @param {*} value Value to freeze.
* @return {*} Frozen value.
* @param {*} object Object to freeze.
* @return {*} Frozen object.
*/

@@ -233,2 +264,14 @@

/**
* Protects the object.
*
* @static
* @param {*} object Object to protect.
* @return {*} Protected object.
*/
static protect(object) {
return _protect(object);
}
/**
* Create NodeVM instance.

@@ -235,0 +278,0 @@ *

2

package.json

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

],
"version": "3.3.1",
"version": "3.4.0",
"main": "index.js",

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

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

before(done => {
before(() => {
vm = new VM({sandbox});
done();
})
it('common', done => {
it('common', () => {
assert.ok(vm.run(`global.__proto__ === Object.prototype`));

@@ -103,7 +102,5 @@ assert.ok(vm.run(`global.__proto__.constructor === Object`));

assert.strictEqual(o.a === o.b, true);
done();
})
it('class', done => {
it('class', () => {
assert.strictEqual(vm.run("new test.klass()").isVMProxy, undefined);

@@ -114,40 +111,28 @@ assert.strictEqual(vm.run("new test.klass()").greet('friend'), 'hello friend');

//vm.run("class LocalClass extends test.klass {}");
done();
})
it('string', done => {
it('string', () => {
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 => {
it('number', () => {
assert.strictEqual(vm.run("typeof(test.numberO) === 'number' && test.number.valueOf instanceof Object"), true);
done();
})
it('boolean', done => {
it('boolean', () => {
assert.strictEqual(vm.run("typeof(test.booleanO) === 'boolean' && test.boolean.valueOf instanceof Object"), true);
done();
})
it('date', done => {
it('date', () => {
assert.strictEqual(vm.run("test.date instanceof Date"), true);
assert.strictEqual(vm.run("test.date") instanceof Date, true);
assert.strictEqual(vm.run("test.date"), sandbox.test.date);
done();
})
it('regexp', done => {
it('regexp', () => {
assert.strictEqual(vm.run("test.regexp instanceof RegExp"), true);
done();
})
it('buffer', done => {
it('buffer', () => {
assert.strictEqual(vm.run("test.buffer.inspect()"), '<Buffer 00 01>', '#1');

@@ -193,15 +178,11 @@ assert.strictEqual(vm.run("test.buffer instanceof Buffer"), true, '#2');

assert.ok(d.constructor.constructor === Function);
done();
})
it('function', done => {
it('function', () => {
assert.strictEqual(vm.run("test.function instanceof Function"), true, '#1');
assert.strictEqual(vm.run("test.function() instanceof Function"), true, '#2');
assert.strictEqual(vm.run("test.function()() instanceof Object"), true, '#3');
done();
})
it('object', done => {
it('object', () => {
assert.strictEqual(vm.run("test.object instanceof Object && test.object.x === 1"), true, '#1');

@@ -214,19 +195,13 @@ assert.strictEqual(vm.run("test.object.y instanceof Function"), true, '#2');

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

@@ -239,16 +214,10 @@ assert.strictEqual(vm.run("test.symbol1.constructor.constructor === Function"), true);

assert.strictEqual(vm.run("Symbol.keyFor(test.symbol2)"), 'foo');
done();
})
it('error', done => {
it('error', () => {
assert.strictEqual(vm.run("Object.getOwnPropertyDescriptor(test.error, 'stack').get.constructor === Function;"), true);
done();
})
after(done => {
after(() => {
vm = null;
done();
})

@@ -260,3 +229,3 @@ })

before(done => {
before(() => {
let sandbox = {

@@ -282,13 +251,9 @@ round(number) { return Math.round(number); },

})
done();
})
it('globals', done => {
it('globals', () => {
assert.equal(vm.run("round(1.5)"), 2);
done();
})
it('errors', done => {
it('errors', () => {
assert.throws(() => vm.run("notdefined"), /notdefined is not defined/);

@@ -300,7 +265,5 @@ assert.throws(() => vm.run("Object.setPrototypeOf(sub, {})"), err => {

})
done();
})
it('timeout', done => {
it('timeout', () => {
assert.throws(() => new VM({

@@ -310,15 +273,11 @@ timeout: 10

assert.throws(() => vm.run("sub.getter"), /Script execution timed out\./);
done();
})
it('timers', done => {
it('timers', () => {
assert.equal(vm.run("global.setTimeout"), void 0);
assert.equal(vm.run("global.setInterval"), void 0);
assert.equal(vm.run("global.setImmediate"), void 0);
done();
})
it('various attacks #1', done => {
it('various attacks #1', () => {
let vm2 = new VM({sandbox: {log: console.log, boom: function() { throw new Error(); }}});

@@ -375,7 +334,5 @@

`)(new Buffer(1)), '#7');
done();
})
it('various attacks #2', done => {
it('various attacks #2', () => {
let vm2 = new VM({

@@ -450,10 +407,6 @@ sandbox: {

`));
done();
})
after(done => {
after(() => {
vm = null;
done();
})

@@ -465,53 +418,37 @@ })

before(done => {
before(() => {
vm = new NodeVM;
done();
})
it('globals', done => {
it('globals', () => {
let ex;
ex = vm.run("module.exports = global");
assert.equal(ex.isVM, true);
done();
})
it('errors', done => {
it('errors', () => {
assert.throws(() => vm.run("notdefined"), /notdefined is not defined/);
done();
})
it('prevent global access', done => {
it('prevent global access', () => {
assert.throws(() => vm.run("process.exit()"), /(undefined is not a function|process\.exit is not a function)/);
done();
})
it('arguments attack', done => {
it('arguments attack', () => {
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 => {
it('global attack', () => {
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 => {
it.skip('timeout (not supported by Node\'s VM)', () => {
assert.throws(() => new NodeVM({
timeout: 10
}).run("while (true) {}"), /Script execution timed out\./);
done();
})
after(done => {
after(() => {
vm = null;
done();
})

@@ -521,3 +458,3 @@ })

describe('modules', () => {
it('require json', done => {
it('require json', () => {
let vm = new NodeVM({

@@ -530,7 +467,5 @@ require: {

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

@@ -544,15 +479,11 @@ require: {

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

@@ -583,7 +514,5 @@ require: {

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

@@ -596,7 +525,5 @@ require: {

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

@@ -609,7 +536,5 @@ require: {

vm.run("require('foobar')", __filename);
done();
})
it('arguments attack', done => {
it('arguments attack', () => {
let vm = new NodeVM;

@@ -622,4 +547,2 @@

assert.throws(() => vm.run("module.exports = function fce(msg) { return fce.caller.toString(); }")(), /Cannot read property 'toString' of null/);
done();
})

@@ -641,3 +564,3 @@

it('path attack', done => {
it('path attack', () => {
let vm = new NodeVM({

@@ -651,7 +574,5 @@ require: {

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 => {
it('process events', () => {
let vm = new NodeVM({

@@ -670,4 +591,2 @@ sandbox: {

assert.strictEqual(sandbox.VM2_COUNTER, 1);
done();
})

@@ -690,3 +609,3 @@

it('mock', done => {
it('mock', () => {
let vm = new NodeVM({

@@ -704,4 +623,2 @@ require: {

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

@@ -711,3 +628,3 @@ })

describe('nesting', () => {
it('NodeVM', done => {
it('NodeVM', () => {
let vm = new NodeVM({

@@ -725,4 +642,2 @@ nesting: true

assert.strictEqual(nestedObject.constructor.constructor === Function, true);
done();
})

@@ -732,3 +647,3 @@ })

describe('wrappers', () => {
it('none', done => {
it('none', () => {
let vm = new NodeVM({

@@ -739,4 +654,2 @@ wrapper: 'none'

assert.strictEqual(vm.run('return 2 + 2'), 4)
done()
})

@@ -746,3 +659,3 @@ })

describe('precompiled scripts', () => {
it('VM', done => {
it('VM', () => {
let vm = new VM();

@@ -754,7 +667,5 @@ let script = new VMScript("Math.random()");

assert.ok( val1 != val2);
done()
})
it('NodeVM', done => {
it('NodeVM', () => {
let vm = new NodeVM();

@@ -766,9 +677,7 @@ let script = new VMScript("module.exports = Math.random()");

assert.ok( val1 != val2);
done()
})
})
describe('read-only contextified items', () => {
it('without read-only', done => {
describe('freeze, protect', () => {
it('without freeze', () => {
let x = {

@@ -790,7 +699,5 @@ a: () => 'a',

assert.strictEqual(x.c.d(), '---');
done()
})
it('with read-only', done => {
it('with freeze', () => {
let x = VM.freeze({

@@ -819,5 +726,22 @@ a: () => 'a',

}, /Object is read-only\./);
})
done()
it('without protect', () => {
let vm = new VM(), obj = {};
vm.run('(i) => { i.text = "test" }')(obj);
vm.run('(i) => { i.func = () => {} }')(obj);
vm.run('(i) => { delete i.func }')(obj);
})
it('with protect', () => {
let vm = new VM(), obj = {};
vm.run('(i) => { i.text = "test" }')(obj);
assert.throws(() => {
vm.run('(i) => { i.func = () => {} }')(VM.protect(obj));
}, /Assigning a function to protected object is prohibited\./);
vm.run('(i) => { delete i.func }')(VM.protect(obj));
})
})
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