I want to run some untrusted code in Node that might look like this:
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
Using Fibers, I got the synchronous behaviour working as expected:
var Fiber = require('fibers');
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
Fiber(function(){
for (var i = 0; i < 5; i++){
green_led(1);
sleep(500);
green_led(0);
sleep(500);
}
}).run();
The difficulty is how to sandbox the code. Having to use Fibers makes it really complicated; I'm not really sure how to start. How might I get the above sandboxed with vm2? For example, the following obviously won't work:
var code = "\
for (var i = 0; i < 5; i++){\
green_led(1);\
sleep(500);\
green_led(0);\
sleep(500);\
}\
";
function sleep(ms){
var fiber = Fiber.current;
setTimeout(function(){ fiber.run(); }, ms);
Fiber.yield();
}
function green_led(active){
//...
}
Fiber(function(){
vm.run(code);
}).run();
(It won't work because green_led and sleep are not visible to the sandboxed code in the VM).
How should this be done? Either...
- Perhaps everything should be run inside the VM, including Fibers and implementation of
green_ledetc? - Or would it be better to keep code run by the VM minimal, and instead somehow whitelist/proxy
green_ledandsleep? Not exactly easy on the gray matter, it's hard enough understanding how Fibers work in the first place!
It's actually quite straight-forward.
The above approach passes in a reference to
Fiberand the other functionssleepandgreen_ledvia the sandbox object. This could be done in other ways. For example,sleepandgreen_ledcould be defined within the string passed tovm.run(), and the vm could itselfincludefiberslike so:As per the documentation, notice the difference between
VMandNodeVM. Out of the above two methods, only the first would be able to make use of the timeout feature. Also, the second method is not immune towhile (true) {}etc.