laverdet / isolated-vm

Secure & isolated JS environments for nodejs
ISC License
2.19k stars 154 forks source link

unable to modify built-in object prototypes #471

Closed Lakshmanshankar closed 6 months ago

Lakshmanshankar commented 6 months ago

Environment

Node.js version: v20.12.0 Operating System: Ubuntu 22.04 isolated-vm version: 4.7.2

Support for modifying built-in object prototypes in isolated-vm

I am facing a limitation where I cannot modify the prototypes of built-in objects like Array within the isolated context, nor can I return an array at the end. However, I am able to modify the prototypes of String and Number.

import iso from "isolated-vm"

const isolate = new iso.Isolate({ memoryLimit: 128 })

const context = isolate.createContextSync();

const jail = context.global;
jail.setSync('global', jail.derefInto());

const res = context.evalSync(`
Array.prototype.of = function(index) {
    return [...this.values()][index]
}

String.prototype.of = function(index) {
    return [...this.valueOf()][index]
}

// "hello".of(1)
// [1,2,3].of(1)
`);

console.log(res)

It would be really helpful if there was a way to securely modify the prototypes of built-in objects within the isolated context.

laverdet commented 6 months ago

This isn't an issue in isolated-vm. Since you don't have a semicolon at the end of the String.prototype.of assignment, you are actually accessing 3 of String.prototype.of. e.g. String.prototype.of[3].of(1).

You can observe using plain nodejs:

$ cat a.mjs 
Array.prototype.of = function(index) {
    return [...this.values()][index]
}

String.prototype.of = function(index) {
    return [...this.valueOf()][index]
}

// "hello".of(1)
[1,2,3].of(1)

$ node a.mjs 
file:///Users/marcel/a.mjs:10
[1,2,3].of(1)
        ^

TypeError: Cannot read properties of undefined (reading 'of')
    at file:///Users/marcel/a.mjs:10:9
    at ModuleJob.run (node:internal/modules/esm/module_job:262:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:474:24)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:119:5)

Node.js v22.1.0

You can read more about semicolon insertion and the lexical grammar of js on mdn: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion

Lakshmanshankar commented 6 months ago

Thank for your response. That is a mistake on my side but can we return arrays at the end of the evalSync. I got undefined

import iso from "isolated-vm";

const isolate = new iso.Isolate({ memoryLimit: 128 });

const context = isolate.createContextSync();

const jail = context.global;
jail.setSync("global", jail.derefInto());

const res = context.evalSync(`
Array.prototype.foo = function() {
    return [...this.values()]
};

[1,2,3].foo()
`);

Array.prototype.foo = function () {
  return [...this.values()];
};

console.log([1, 2, 3].foo(), res); // [1,2,3] undefined
laverdet commented 5 months ago

Arrays are not transferable. Look at TransferOptions in the docs