В ноде есть встроенный механизм песочницы для запуска опасного кода. vm.runInNewContext(<код>, <контекст>) и погнали. Лучше и безопаснее eval, но... со своими проблемами. Всё ещё можно вылезти из песочницы и ударить в глобал. this.constructor.constructor и побежали веселиться.



Но вот ещё про одну забавную проблему расскажу.



Как можно подвесить процесс через песочницу? Очень просто:





vm.runInNewContext('while(true){}',{});





Но вы скажете, что есть же параметр timeout:





vm.runInNewContext('while(true){}',{timeout: 5});





Уже лучше. Но проблема в том, что timeout не ловит микротаски. Выносим луп в микротаску и снова DoS





vm.runInNewContext(

'Promise.resolve().then(()=>{while(true) {}});',

{},

{timeout:5}

);





Ок, проблема известная, в 15-й ноде дырку заделали фанерой.





vm.runInNewContext(

'Promise.resolve().then(()=>{while(true) {}});',

{},

{timeout:5, microtaskMode: 'afterEvaluate'}

);





Почему такое апи? Ума не приложу :) Но в этом режиме песочница разматывает микротаски сразу после макротасок и таймаут общий. Почти хорошо стало, но что если мы решили передать в песочницу что-нибудь асинхронное? И пользователь сможет выйти на следующий луп. Тогда ой:





vm.runInNewContext(

`

setTimeout(() => {

while(true) {};

}, 10000);`,

{setTimeout},

{timeout:5, microtaskMode: 'afterEvaluate'}

);





Всё попало, шеф. У нас DoS.



В общем, посмотрите лучше на vm2 или на более интересную изоляцию через isolated-vm