结合NodeJS Fibers + VM Sandbox

我想在Node中运行一些不受信任的代码,如下所示:

for (var i = 0; i < 5; i++){ green_led(1); sleep(500); green_led(0); sleep(500); } 

使用光纤,我得到了同步行为按预期工作:

 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(); 

难题是如何沙箱代码。 不得不使用Fibers使其变得非常复杂; 我不确定如何开始。 我怎样才能得到以上与vm2沙盒? 例如,以下显然不会工作:

 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(); 

(这将无法正常工作,因为green_ledsleep对虚拟机中的沙盒代码不可见)。

这应该怎么做? 要么…

  1. 也许一切都应该在虚拟机内运行,包括光纤和green_led实施等?
  2. 或者,最好是保持虚拟机运行的代码最小,而不是白名单/代理green_ledsleep ? 在灰色的问题上不是很容易,很难理解纤维如何在第一位工作!

其实挺简单的

 var Fiber = require('fibers'); const {VM} = require('vm2'); const vm = new VM({ sandbox: { green_led: green_led, sleep: sleep } }); function sleep(ms){ var fiber = Fiber.current; setTimeout(function(){ fiber.run(); }, ms); Fiber.yield(); } function green_led(active){ //... } vm.run( `Fiber(function(){ for (var i = 0; i < 5; i++){ green_led(1); sleep(500); green_led(0); sleep(500); } }).run()` ); 

上面的方法传递一个对Fiber的引用,其他函数通过沙箱对象sleepgreen_led 。 这可以通过其他方式来完成。 例如,可以在传递给vm.run()的string中定义sleepgreen_led ,并且vm本身可以include像这样的fibers

 const {NodeVM} = require('vm2'); var vm = new NodeVM({ require: { external: true, } }); vm.run( ` 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()` ); 

根据文档 ,请注意VMNodeVM之间的区别。 在以上两种方法中,只有第一种方法能够使用超时function。 另外,第二种方法对while (true) {}等不是免疫的

Interesting Posts