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_led
etc? - Or would it be better to keep code run by the VM minimal, and instead somehow whitelist/proxy
green_led
andsleep
? 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
Fiber
and the other functionssleep
andgreen_led
via the sandbox object. This could be done in other ways. For example,sleep
andgreen_led
could be defined within the string passed tovm.run()
, and the vm could itselfinclude
fibers
like so:As per the documentation, notice the difference between
VM
andNodeVM
. 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.