UNPKG

pitboss-ng

Version:

Run untrusted code in a seperate process using VM2 module. With timeout and memory limit management

95 lines (79 loc) 1.82 kB
const { VM } = require('vm2'); const clone = require('clone'); let sandboxedCode = null; let script = null; let errorStatusMsg = null; let errorStatus = 0; let timeout = undefined; const STATUS = { FATAL: 1 }; process.on('message', function onMessage(msg) { if (msg['code']) { if (msg['timeout']) { timeout = parseInt(msg['timeout'], 10); } create(msg['code']); } else { run(msg); } }); function create(code) { sandboxedCode = `"use strict";\n${code}\n`; }; function run(msg) { if (isFatalError()) { error(errorStatusMsg, msg.id); return false; } if (!sandboxedCode) { error("No code to run"); return false; } if (msg.context == null) { msg.context = {}; } const sandbox = clone(msg.context) || {}; if (msg.libraries) { if (Array.isArray(msg.libraries)) { msg.libraries.forEach((lib) => { sandbox[lib] = require(lib); }); } else if (typeof msg.libraries === 'object') { Object.keys(msg.libraries).forEach((libKey) => { sandbox[libKey] = require(msg.libraries[libKey]); }); } else { return error("Pitboss error: Libraries must be defined by an array or by an object.", msg.id); } } try { script = new VM({ sandbox, timeout, }); const result = script.run(sandboxedCode) || null; const res = { result: result, // script can return undefined, ensure it's null id: msg.id, }; message(res); } catch (err) { error(`VM Runtime Error: ${err}`, msg.id); } }; function isFatalError() { if (errorStatus === STATUS['FATAL']) { return true; } else { return false; } }; function error(msg, id = null) { return message({ error: msg, id }); }; function message(msg) { process.send(msg); }; message('ready');