patriksimek / vm2

Advanced vm/sandbox for Node.js
MIT License
3.86k stars 294 forks source link

__proto__ property of a Proxy wrapping an object not containing __proto__ property behaves differently from expected that. #473

Closed kagesakura closed 1 year ago

kagesakura commented 1 year ago

For instance, it is expected to return undefined, but null is returned.

const { VM } = require('vm2');

console.log(new VM().run('({ __proto__: null })').__proto__);
// output(VM): null

console.log({ __proto__: null }.__proto__);
// output(normal): undefined
XmiliaH commented 1 year ago

This is expected. In case the object does not have a __proto__ property VM emulates it even if there is a __proto__ property in the prototype chain or, as in your case there is none. The value of the __proto__ property in the chain does also not matter.

const { VM } = require('vm2');

console.log(new VM().run('({ __proto__: { __proto__: null, ["__proto__"]: 1 } })').__proto__);
// output(VM): [Object: null prototype] {}

console.log({ __proto__: { __proto__: null, ["__proto__"]: 1 } }.__proto__);
// output(normal): 1

This is done for a reason and will not be changed.

XmiliaH commented 1 year ago

Since scripts should not get access to prototypes. If they could it would be trivial to get the Function constructor and escape. Therefore __proto__ is handled specially and a sandboxed prototype is returned instead.