
Sandbox Node.js per eseguire JavaScript non attendibile in-process, utilizzando Proxy e un require controllato per limitare l'accesso ai moduli integrati ed esterni.
vm2 è una sandbox in grado di eseguire codice non attendibile con i moduli integrati di Node inseriti in una whitelist.
Per uno sguardo approfondito al funzionamento interno di vm2, consulta il file CONTRIBUTING.md.
Provalo tu stesso:
import { runInNewContext } from "node:vm";
runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');
import { VM } from 'vm2';
new VM().run('this.constructor.constructor("return process")().exit()');
// Throws ReferenceError: process is not defined
npm install vm2
import { VM } from 'vm2';
const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function
import { NodeVM } from 'vm2';
const vm = new NodeVM({
require: {
external: true,
root: './',
},
});
vm.run(
`
var request = require('request');
request('http://www.google.com', function (error, response, body) {
console.error(error);
if (!error && response.statusCode == 200) {
console.log(body); // Show the HTML for the Google homepage.
}
});
`,
'vm.js',
);
VM è una sandbox semplice per eseguire in modo sincrono codice non attendibile senza la funzionalità require. Sono disponibili solo gli oggetti integrati di JavaScript e il Buffer di Node. Le funzioni di pianificazione (setInterval, setTimeout e setImmediate) non sono disponibili per impostazione predefinita.
Opzioni:
timeout - Timeout dello script in millisecondi. ATTENZIONE: potresti voler usare questa opzione insieme a allowAsync=false. Inoltre, operare sugli oggetti restituiti dalla sandbox può eseguire codice arbitrario ed eludere il timeout. Si dovrebbe verificare se l'oggetto restituito è un primitivo con typeof e scartarlo completamente (anche eseguire il logging o creare messaggi di errore con un tale oggetto potrebbe eseguire nuovamente codice arbitrario) nel caso contrario.sandbox - L'oggetto globale della VM.compiler - javascript (predefinito), typescript, coffeescript o una funzione di compilazione personalizzata. La libreria presuppone che tu abbia il compilatore preinstallato se il valore è impostato su typescript o coffeescript.eval - Se impostato su false, qualsiasi chiamata a eval o ai costruttori di funzioni (Function, GeneratorFunction, ecc.) genererà un EvalError (predefinito: true).wasm - Se impostato su false, qualsiasi tentativo di compilare un modulo WebAssembly genererà un WebAssembly.CompileError (predefinito: true).allowAsync - Se impostato su false, qualsiasi tentativo di eseguire codice usando async genererà un VMError (predefinito: true).IMPORTANTE: Il timeout è efficace solo sul codice sincrono che esegui tramite run. Il timeout NON funziona su alcun metodo restituito da VM. Ci sono alcune situazioni in cui il timeout non funziona - vedi #244.
import { VM } from 'vm2';
const vm = new VM({
timeout: 1000,
allowAsync: false,
sandbox: {},
});
vm.run('process.exit()'); // throws ReferenceError: process is not defined
Puoi anche recuperare valori dalla VM.
let number = vm.run('1337'); // returns 1337
SUGGERIMENTO: consulta i test per ulteriori esempi d'uso.
A differenza di VM, NodeVM consente di richiedere moduli allo stesso modo in cui lo faresti nel contesto di Node normale.
Opzioni: