Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
vm2 — Sandbox JavaScript isolato per Node.js che esegue codice non attendibile con accesso limitato ai moduli integrati e alle risorse host tramite intercettazione basata su Proxy. | Kitploit
Strumenti/GitHubGitHub/patriksimek/vm2
Analisi Dinamica (Sandboxing)Analisi del CodiceVirtualizzazione per la SicurezzaUtilità e Framework
GitHubpatriksimek/vm2

vm2

Sandbox JavaScript isolato per Node.js che esegue codice non attendibile con accesso limitato ai moduli integrati e alle risorse host tramite intercettazione basata su Proxy.

Vedi Repository
4.1k3265 giorni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![License][license-image]][license-url] Node.js CI [![Known Vulnerabilities][snyk-image]][snyk-url]

vm2 è una sandbox che può eseguire codice non attendibile con i moduli built-in di Node consentiti.

Importante avvertenza sulla sicurezza

Prima di usare vm2, dovresti capire come funziona e quali sono i suoi limiti.

vm2 tenta di isolare codice JavaScript non attendibile all'interno dello stesso processo Node.js della tua applicazione. Lo fa attraverso una complessa rete di Proxy che intercettano e mediano ogni interazione tra la sandbox e l'ambiente host.

La sfida fondamentale

JavaScript è un linguaggio straordinariamente dinamico. Gli oggetti possono essere raggiunti attraverso le catene di prototipi, i costruttori possono essere ottenuti tramite gli oggetti di errore, i symbol forniscono hook di protocollo e l'esecuzione asincrona crea finestre temporali. L'enorme numero di modi per passare da un oggetto all'altro in JavaScript rende estremamente difficile costruire una sandbox in-process a prova di fuga.

Siamo onesti su questa realtà: nonostante i nostri migliori sforzi, ricercatori e professionisti della sicurezza scoprono continuamente nuovi modi per evadere dalla sandbox di vm2. Correggiamo attivamente queste vulnerabilità quando vengono segnalate, ma la natura di "gatto e topo" dell'isolamento in-process implica che:

  1. In futuro verranno probabilmente scoperti nuovi bypass. Controlla i nostri security advisories per le vulnerabilità note.
  2. Devi mantenere vm2 aggiornato per beneficiare delle ultime correzioni di sicurezza. Iscriviti agli advisory di sicurezza e aggiorna tempestivamente.
  3. vm2 non dovrebbe essere la tua unica linea di difesa. La difesa in profondità è essenziale quando si esegue codice non attendibile.

Alternative più robuste

Se hai bisogno di garanzie di isolamento più forti, considera queste alternative che forniscono un vero isolamento a livello di processo o hardware:

Quando vm2 può essere comunque appropriato

vm2 può essere adatto quando:

  • Hai bisogno di una stretta integrazione con gli oggetti host e di una comunicazione sincrona veloce
  • Il codice non attendibile proviene da una fonte relativamente fidata (es. strumenti interni, sistemi di plugin con autori verificati)
  • Combini vm2 con altri livelli di sicurezza (isolamento di rete, restrizioni sul filesystem, limiti alle risorse)
  • Accetti il rischio e monitori attivamente gli aggiornamenti di sicurezza

Se esegui codice proveniente da fonti completamente non attendibili (es. invii arbitrari da parte degli utenti), ti consigliamo vivamente di utilizzare una soluzione con garanzie di isolamento più forti.

Caratteristiche

  • Esegue codice non attendibile in modo sicuro in un singolo processo, affiancato al tuo codice
  • Controllo totale sull'output della console della sandbox
  • La sandbox ha accesso limitato ai metodi del processo
  • È possibile richiedere moduli (built-in ed esterni) dalla sandbox
  • Puoi limitare l'accesso a determinati moduli built-in (o a tutti)
  • Puoi chiamare metodi in modo sicuro e scambiare dati e callback tra le sandbox
  • Mantenuto attivamente con patch per i metodi di fuga noti (vedi Avvertenza sulla sicurezza)
  • Supporto del transpiler

Come funziona

  • Usa il modulo VM interno per creare un contesto sicuro.
  • Usa Proxy per impedire la fuga dalla sandbox.
  • Sovrascrive la require built-in per controllare l'accesso ai moduli.

Per uno sguardo approfondito agli internals di vm2, consulta il file CONTRIBUTING.md.

Qual è la differenza tra il modulo vm di Node e vm2?

Provalo tu stesso:```js import { runInNewContext } from "node:vm";

runInNewContext('this.constructor.constructor("return process")().exit()'); console.log('Never gets executed.');

root@kitploit:~
Arriveremo a come caricarli ed eseguirli, una volta che avremo capito cosa fanno.```js
import { VM } from 'vm2';

new VM().run('this.constructor.constructor("return process")().exit()');
// Throws ReferenceError: process is not defined

Installazione```sh

npm install vm2

root@kitploit:~
## Esempi rapidi```js
import { VM } from 'vm2';

const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function

Since the input chunk is empty, there is no text to translate.```js 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', );

root@kitploit:~
## Documentazione

-   [VM](#vm)
-   [NodeVM](#nodevm)
-   [VMScript](#vmscript)
-   [Gestione degli errori](#error-handling)
-   [Debug del codice in sandbox](#debugging-a-sandboxed-code)
-   [Oggetti di sola lettura](#read-only-objects-experimental)
-   [Oggetti protetti](#protected-objects-experimental)
-   [Relazioni tra sandbox](#cross-sandbox-relationships)
-   [CLI](#cli)
-   [Modifiche da 2.x a 3.x](https://github.com/patriksimek/vm2/wiki/2.x-to-3.x-changes)
-   [Documentazione 1.x e 2.x](https://github.com/patriksimek/vm2/wiki/1.x-and-2.x-docs)
-   [Contributi](https://github.com/patriksimek/vm2/wiki/Contributing)

## VM

VM è una semplice sandbox per eseguire in modo sincrono codice non attendibile senza la funzionalità `require`. Sono disponibili solo gli oggetti incorporati 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 su oggetti restituiti dalla sandbox può eseguire codice arbitrario e aggirare il timeout. Si dovrebbe verificare se l'oggetto restituito è un primitivo con `typeof` e, in caso contrario, scartarlo completamente (fare logging o creare messaggi di errore con un tale oggetto potrebbe anche eseguire nuovamente codice arbitrario).
-   `sandbox` - Oggetto globale della VM.
-   `compiler` - `javascript` (predefinito), `typescript`, `coffeescript` o funzione di compilatore personalizzata. La libreria si aspetta 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`). Nota: `WebAssembly.JSTag` viene rimosso all'interno della sandbox per motivi di sicurezza, quindi il codice wasm non può catturare le eccezioni JavaScript.
-   `allowAsync` - Se impostato su `false`, qualsiasi tentativo di eseguire codice usando `async` genererà un `VMError` (predefinito: `true`).
-   `bufferAllocLimit` - Dimensione massima in byte per una singola richiesta `Buffer.alloc` / `Buffer.allocUnsafe` / `Buffer.allocUnsafeSlow` / `Buffer(N)` / `new Buffer(N)` dall'interno della sandbox. Le richieste che superano questo limite generano un `RangeError` in modo sincrono senza eseguire l'allocazione host. Predefinito: `Infinity` (nessun limite, completamente retrocompatibile). Gli embedder che eseguono codice non attendibile in ambienti con memoria limitata (Docker / Kubernetes / Lambda / serverless) dovrebbero adottare un limite finito (ad es. `32 * 1024 * 1024`) come parte di una difesa DoS a strati, allo stesso modo in cui adottano `timeout`. Vedi [Raccomandazioni di hardening](#hardening-recommendations) di seguito.

**IMPORTANTE**: Il timeout è efficace solo su codice sincrono eseguito tramite `run`. Il timeout **NON** funziona su alcun metodo restituito dalla VM. Ci sono alcune situazioni in cui il timeout non funziona - vedi [#244](https://github.com/patriksimek/vm2/pull/244).```js
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.```js let number = vm.run('1337'); // returns 1337

root@kitploit:~
**SUGGERIMENTO**: Consulta i test per ulteriori esempi di utilizzo.

## NodeVM

A differenza di `VM`, `NodeVM` consente di richiedere moduli nello stesso modo in cui si farebbe nel contesto regolare di Node.

**Opzioni:**

-   `console` - `inherit` per abilitare la console, `redirect` per reindirizzare agli eventi, `off` per disabilitare la console (default: `inherit`).
-   `sandbox` - L'oggetto globale della VM.
-   `compiler` - `javascript` (default), `typescript`, `coffeescript` o una funzione compilatore personalizzata (che riceve il codice e il suo percorso file). La libreria si aspetta che tu abbia il compilatore preinstallato se il valore è impostato su `typescript` o `coffeescript`.
-   `eval` - Se impostato a `false`, qualsiasi chiamata a `eval` o a costruttori di funzioni (`Function`, `GeneratorFunction`, ecc.) lancerà un `EvalError` (default: `true`).
-   `wasm` - Se impostato a `false`, qualsiasi tentativo di compilare un modulo WebAssembly lancerà un `WebAssembly.CompileError` (default: `true`). Nota: `WebAssembly.JSTag` viene rimosso all'interno della sandbox per motivi di sicurezza, quindi il codice wasm non può catturare eccezioni JavaScript.
-   `bufferAllocLimit` - Stessa semantica di `VM` — dimensione massima in byte per una singola richiesta della famiglia `Buffer.alloc` dall'interno della sandbox. Default: `Infinity`. Vedi [Raccomandazioni di hardening](#hardening-recommendations).
-   `sourceExtensions` - Array di estensioni di file da trattare come codice sorgente (default: `['js']`).
-   `require` - `true`, un oggetto o un Resolver per abilitare il metodo `require` (default: `false`).
-   `require.external` - I valori possono essere `true`, un array di moduli esterni consentiti, o un oggetto (default: `false`). Tutti i percorsi che corrispondono a `/node_modules/${any_allowed_external_module}/(?!/node_modules/)` possono essere richiesti.
-   `require.external.modules` - Array di moduli esterni consentiti. Supporta anche i wildcard, quindi specificare `['@scope/*-ver-??]`, ad esempio, consentirà di utilizzare tutti i moduli con un nome della forma `@scope/something-ver-aa`, `@scope/other-ver-11`, ecc. Il wildcard `*` non corrisponde ai separatori di percorso.
-   `require.external.transitive` - Booleano che indica se le dipendenze transitive dei moduli esterni sono consentite (default: `false`). **ATTENZIONE**: Quando un modulo viene richiesto in modo transitivo, qualsiasi modulo può poi richiederlo normalmente, anche se non era possibile prima che fosse caricato.
-   `require.builtin` - Array di moduli integrati consentiti, accetta ["\*"] per tutti (default: nessuno). **ATTENZIONE**: "\*" può essere pericoloso perché nuovi moduli integrati possono essere aggiunti.
-   `require.root` - Percorso/i ristretto/i in cui i moduli locali possono essere richiesti (default: ogni percorso).
-   `require.mock` - Collezione di moduli mock (sia esterni che integrati).
-   `require.context` - `host` (default) per richiedere moduli nell'host e inoltrarli nella sandbox. `sandbox` per caricare, compilare e richiedere moduli nella sandbox. `callback(moduleFilename, ext)` per scegliere dinamicamente un contesto per ogni modulo. Il default sarà la sandbox se non viene specificato nulla. Ad eccezione di `events`, i moduli integrati vengono sempre richiesti nell'host e inoltrati nella sandbox.
-   `require.import` - Un array di moduli da caricare in NodeVM all'avvio.
-   `require.resolve` - Una funzione di ricerca aggiuntiva nel caso in cui un modulo non venga trovato in uno dei percorsi di ricerca tradizionali di Node.
-   `require.customRequire` - Da usare al posto della funzione `require` per caricare moduli dall'host.
-   `require.strict` - `false` per non forzare la modalità strict sui moduli caricati da require (default: `true`).
-   `require.fs` - Implementazione personalizzata del file system.
-   `nesting` - **ATTENZIONE**: Consentire questo è un rischio per la sicurezza poiché gli script possono creare una NodeVM che può richiedere qualsiasi modulo dell'host. `true` per abilitare l'annidamento delle VM (default: `false`).
-   `wrapper` - `commonjs` (default) per avvolgere lo script in un wrapper CommonJS, `none` per recuperare il valore restituito dallo script.
-   `argv` - Array da passare a `process.argv`.
-   `env` - Oggetto da passare a `process.env`.
-   `strict` - `true` per caricare i moduli in modalità strict (default: `false`).

**IMPORTANTE**: Il timeout non è efficace per NodeVM, quindi non è immune a `while (true) {}` o simili nefandezze.

**RICORDA**: Più moduli consenti, più la tua sandbox diventa fragile.```js
import { NodeVM } from 'vm2';

const vm = new NodeVM({
	console: 'inherit',
	sandbox: {},
	require: {
		external: true,
		builtin: ['fs', 'path'],
		root: './',
		mock: {
			fs: {
				readFileSync: () => 'Nice try!',
			},
		},
	},
});

// Sync

let functionInSandbox = vm.run('module.exports = function(who) { console.log("hello "+ who); }');
functionInSandbox('world');

// Async

let functionWithCallbackInSandbox = vm.run('module.exports = function(who, callback) { callback("hello "+ who); }');
functionWithCallbackInSandbox('world', greeting => {
	console.log(greeting);
});

Quando wrapper è impostato su none, NodeVM si comporta più come VM per codice sincrono.```js assert.ok(vm.run('return true') === true);

root@kitploit:~
**CONSIGLIO**: Vedi i test per ulteriori esempi di utilizzo.

### Caricare moduli tramite percorso relativo

Per caricare moduli tramite percorso relativo, devi passare il percorso completo dello script che stai eseguendo come secondo argomento al metodo `run` di vm se lo script è una stringa. Il nome del file viene quindi visualizzato in qualsiasi stack trace generato dallo script.```js
vm.run('require("foobar")', '/data/myvmscript.js');

Se lo script che stai eseguendo è un VMScript, il percorso è fornito nel costruttore VMScript.```js const script = new VMScript('require("foobar")', { filename: '/data/myvmscript.js' }); vm.run(script);

root@kitploit:~
### Resolver

Un resolver può essere creato tramite `makeResolverFromLegacyOptions` e può essere utilizzato per più istanze `NodeVM`, consentendo di condividere il codice del modulo compilato e potenzialmente accelerando i tempi di caricamento. Il primo esempio di `NodeVM` può essere riscritto utilizzando `makeResolverFromLegacyOptions` come segue.```js
const resolver = makeResolverFromLegacyOptions({
	external: true,
	builtin: ['fs', 'path'],
	root: './',
	mock: {
		fs: {
			readFileSync: () => 'Nice try!',
		},
	},
});
const vm = new NodeVM({
	console: 'inherit',
	sandbox: {},
	require: resolver,
});

VMScript

Puoi aumentare le prestazioni utilizzando script precompilati. Il VMScript precompilato può essere eseguito più volte. È importante notare che il codice non è associato a nessuna VM (contesto); piuttosto, viene associato prima di ogni esecuzione, solo per quella esecuzione.```js import { VM, VMScript } from 'vm2';

const vm = new VM(); const script = new VMScript('Math.random()'); console.log(vm.run(script)); console.log(vm.run(script));

root@kitploit:~
Funziona sia per `VM` che per `NodeVM`.```js
import { NodeVM, VMScript } from 'vm2';

const vm = new NodeVM();
const script = new VMScript('module.exports = Math.random()');
console.log(vm.run(script));
console.log(vm.run(script));

Il codice viene compilato automaticamente la prima volta che viene eseguito. Si può compilare il codice in qualsiasi momento con script.compile(). Una volta che il codice è compilato, il metodo non ha alcun effetto.

Gestione degli errori

Gli errori nella compilazione del codice e nell'esecuzione sincrona del codice possono essere gestiti con try-catch. Gli errori nell'esecuzione asincrona del codice possono essere gestiti collegando un gestore di eventi uncaughtException al process di Node.```js try { var script = new VMScript('Math.random()').compile(); } catch (err) { console.error('Failed to compile script.', err); }

try { vm.run(script); } catch (err) { console.error('Failed to execute script.', err); }

process.on('uncaughtException', err => { console.error('Asynchronous error caught.', err); });

root@kitploit:~
## Debug di un codice in sandbox

Puoi eseguire il debug o ispezionare il codice in esecuzione nella sandbox come se fosse in esecuzione in un normale processo.

-   Puoi usare i punti di interruzione (che richiedono di specificare un nome di file script)
-   Puoi usare la parola chiave `debugger`.
-   Puoi usare step-in per entrare nel codice in esecuzione nella sandbox.

### Esempio

/tmp/main.js:```js
import { VM, VMScript } from 'vm2';
import { readFileSync } from 'node:fs';

const file = `${__dirname}/sandbox.js`;

// By providing a file name as second argument you enable breakpoints
const script = new VMScript(readFileSync(file), file);

new VM().run(script);

/tmp/sandbox.js```js const foo = 'ahoj';

// The debugger keyword works just fine everywhere. // Even without specifying a file name to the VMScript object. debugger;

root@kitploit:~
## Oggetti di sola lettura (sperimentale)

Per impedire agli script in sandbox di aggiungere, modificare o eliminare proprietà dagli oggetti con proxy, puoi usare i metodi `freeze` per rendere l'oggetto di sola lettura. Questo è efficace solo all'interno della VM. Gli oggetti congelati sono influenzati profondamente. I tipi primitivi non possono essere congelati.

**Esempio senza usare `freeze`:**```js
const util = {
	add: (a, b) => a + b,
};

const vm = new VM({
	sandbox: { util },
});

vm.run('util.add = (a, b) => a - b');
console.log(util.add(1, 1)); // returns 0

Esempio con l'utilizzo di freeze:```js const vm = new VM(); // Objects specified in the sandbox cannot be frozen. vm.freeze(util, 'util'); // Second argument adds object to global.

vm.run('util.add = (a, b) => a - b'); // Fails silently when not in strict mode. console.log(util.add(1, 1)); // returns 2

root@kitploit:~
**IMPORTANTE:** Non è possibile congelare oggetti già esposti tramite proxy alla VM.

## Oggetti protetti (sperimentale)

A differenza di `freeze`, questo metodo consente agli script in sandbox di aggiungere, modificare o eliminare proprietà sugli oggetti, con un'eccezione: non è possibile associare funzioni. Gli script in sandbox non sono quindi in grado di modificare metodi come `toJSON`, `toString` o `inspect`.

**IMPORTANTE:** Non è possibile proteggere oggetti già esposti tramite proxy alla VM.

## Relazioni tra sandbox```js
const assert = require('assert');
const { VM } = require('vm2');

const sandbox = {
	object: new Object(),
	func: new Function(),
	buffer: new Buffer([0x01, 0x05]),
};

const vm = new VM({ sandbox });

assert.ok(vm.run(`object`) === sandbox.object);
assert.ok(vm.run(`object instanceof Object`));
assert.ok(vm.run(`object`) instanceof Object);
assert.ok(vm.run(`object.__proto__ === Object.prototype`));
assert.ok(vm.run(`object`).__proto__ === Object.prototype);

assert.ok(vm.run(`func`) === sandbox.func);
assert.ok(vm.run(`func instanceof Function`));
assert.ok(vm.run(`func`) instanceof Function);
assert.ok(vm.run(`func.__proto__ === Function.prototype`));
assert.ok(vm.run(`func`).__proto__ === Function.prototype);

assert.ok(vm.run(`new func() instanceof func`));
assert.ok(vm.run(`new func()`) instanceof sandbox.func);
assert.ok(vm.run(`new func().__proto__ === func.prototype`));
assert.ok(vm.run(`new func()`).__proto__ === sandbox.func.prototype);

assert.ok(vm.run(`buffer`) === sandbox.buffer);
assert.ok(vm.run(`buffer instanceof Buffer`));
assert.ok(vm.run(`buffer`) instanceof Buffer);
assert.ok(vm.run(`buffer.__proto__ === Buffer.prototype`));
assert.ok(vm.run(`buffer`).__proto__ === Buffer.prototype);
assert.ok(vm.run(`buffer.slice(0, 1) instanceof Buffer`));
assert.ok(vm.run(`buffer.slice(0, 1)`) instanceof Buffer);

CLI

Prima di poter usare vm2 nella riga di comando, installalo globalmente con npm install vm2 -g.```sh vm2 ./script.js

root@kitploit:~
## Raccomandazioni di hardening

vm2 previene le fughe dalla sandbox (codice non attendibile che ottiene accesso al reame host). Di per sé **non** previene ogni forma di esaurimento delle risorse o denial-of-service. Gli integratori che eseguono codice non attendibile dovrebbero aggiungere le seguenti difese a strati attorno alla sandbox.

### 1. Limitare l'allocazione di memoria con `bufferAllocLimit`

Una singola chiamata `Buffer.alloc(N)` con `N` controllato dall'attaccante viene eseguita come un'unica allocazione C++ sincrona dell'host che il `timeout` di V8 non può interrompere. In ambienti con memoria limitata, un payload della sandbox di ~100 byte può far aumentare la RSS dell'host di oltre 100 MB e mandare in crash il processo host via OOM. Imposta `bufferAllocLimit` (es. `32 * 1024 * 1024`) per limitare le allocazioni individuali:```js
const vm = new VM({
	timeout: 1000,
	bufferAllocLimit: 32 * 1024 * 1024,
	allowAsync: false,
});

Il tetto si applica anche ai percorsi deprecati Buffer(N) e new Buffer(N). Nota che l'esaurimento aggregato (molte piccole allocazioni, Buffer.concat, Uint8Array, String.repeat, Array(n).fill(), ecc.) non è coperto da questo tetto — combinalo con un limite di memoria lato host (--max-old-space-size, limite del contenitore, cgroup) per una copertura completa.

2. Installa un gestore unhandledRejection lato host

Esiste una classe di DoS da abort del processo host in cui il codice sandbox crea una async function, async function*, o await using il cui corpo lancia un valore che innesca un errore nel reame host durante la formattazione dello stack (ad es. e.name = Symbol(); e.stack). V8 crea la promise di rifiuto tramite la Promise intrinseca del reame, che bypassa il wrapper della sottoclasse Promise di vm2, quindi il rifiuto sfugge all'host come unhandledRejection. Su Node 15+ il comportamento predefinito è terminare il processo.

Chiudere questa falla richiede di modificare il comportamento osservabile dell'host, quindi vm2 non fornisce una correzione di default. Gli integratori dovrebbero installare un gestore a livello di processo che assorba (o registri) i rifiuti provenienti dalla sandbox:```js // Recommended: filter rejections that originated inside vm2 and swallow them, // while letting your own host-side rejections propagate. process.on('unhandledRejection', (reason, promise) => { // Heuristic: rejections from the sandbox frequently surface as values // without proper Error semantics, or with stacks pointing at vm.js. // Adjust the predicate to match your application. if (looksLikeSandboxOrigin(reason)) { return; // swallow — don't terminate the process } // Otherwise: handle (or rethrow) as normal for your host code. yourLogger.error('unhandled rejection', reason); });

root@kitploit:~
Se la tua applicazione non ha altre fonti di rigetti non gestiti, un inghiottimento generale + log è accettabile:```js
process.on('unhandledRejection', reason => {
	yourLogger.warn('swallowed sandbox rejection', reason);
});

Una correzione circoscritta potrebbe essere distribuita dietro un flag opt-in swallowSandboxUnhandledRejections in una futura release minore; fino ad allora, il gestore lato host è la mitigazione consigliata.

3. Esegui con un limite di memoria a livello di processo

Anche con bufferAllocLimit impostato, esegui il processo host con --max-old-space-size (o un limite di memoria del container equivalente) dimensionato per il carico di lavoro. Il limite protegge dalla primitiva di allocazione singola; il limite a livello di OS protegge dall'esaurimento aggregato e da qualsiasi futura primitiva di allocazione che vm2 non ha ancora limitato.

4. Tratta require.builtin: ['*'] come una configurazione non-sandbox

Il carattere jolly '*' si espande alla maggior parte dei moduli built-in di Node, inclusi child_process, fs, dgram, net, http e dns. Questi sono primitive con piena capacità host — require('child_process').execSync('id') è raggiungibile dalla sandbox con '*'. La semantica di '*' di vm2 è intenzionale (alcuni embedder eseguono codice fidato ma isolato), ma non dovrebbe essere usata come impostazione predefinita per codice non fidato. Preferisci una allowlist esplicita del set più piccolo di moduli di cui la tua sandbox ha realmente bisogno.

5. nesting: true è una via di fuga

nesting: true consente al codice della sandbox di fare require('vm2') e costruire NodeVM annidati. La configurazione require della VM annidata è scelta dal codice della sandbox che la costruisce, non vincolata dalla VM esterna. Concretamente:```js const vm = new NodeVM({ nesting: true, require: { builtin: [] } }); vm.run( const { NodeVM: NVM } = require('vm2'); // Inner VM's config is whatever the sandbox writes here: const inner = new NVM({ require: { builtin: ['child_process'] } }); inner.run('require("child_process").execSync("id")'); // RCE);

root@kitploit:~
Se imposti `nesting: true`, hai di fatto concesso alla sandbox lo stesso livello di fiducia che hai tu. **Non abilitare `nesting: true` per codice non affidabile.** Usalo solo quando ti fidi del codice in sandbox ma desideri una semantica di esecuzione in stile VM (global nuovo, timeout controllati) per motivi non legati alla sicurezza.

`nesting: true` **richiede un oggetto di configurazione `require` esplicito** (ad es. `require: { builtin: [] }` o `require: {}`). Qualsiasi altra forma — `require: false`, `require: undefined`, `require: null` o l'omissione completa di `require` — lancia un `VMError` in fase di costruzione (GHSA-m4wx-m65x-ghrr, sostituisce GHSA-8hg8-63c5-gwmx). Tutte queste forme producono un resolver che usa solo NESTING_OVERRIDE: la sandbox può eseguire `require('vm2')` ma nient'altro, il che è una pura primitiva di escape senza alcun uso legittimo. Per negare tutti i require, rimuovi `nesting: true`. Per consentire VM annidate, fornisci una configurazione `require` esplicita così che il compromesso sia visibile nel punto di chiamata.

## Problemi noti

-   Non è possibile definire una classe che estende una classe proxy. Questo include l'uso di una classe proxy in `Object.create`.
-   L'`eval` diretto non funziona.
-   Il log degli array della sandbox ripeterà la parte dell'array nelle proprietà.
-   Le trasformazioni del codice sorgente possono produrre una stringa sorgente diversa per una funzione.
-   Esistono modi per mandare in crash il processo node dall'interno della sandbox. Vedi [Raccomandazioni di hardening](#hardening-recommendations).

[npm-image]: https://img.shields.io/npm/v/vm2.svg
[npm-url]: https://www.npmjs.com/package/vm2
[license-image]: https://img.shields.io/npm/l/vm2.svg
[license-url]: https://raw.githubusercontent.com/patriksimek/vm2/resurrection/LICENSE.md
[downloads-image]: https://img.shields.io/npm/dm/vm2.svg
[downloads-url]: https://www.npmjs.com/package/vm2
[snyk-image]: https://snyk.io/test/github/patriksimek/vm2/badge.svg
[snyk-url]: https://snyk.io/test/github/patriksimek/vm2
Scarica lo strumento
SoluzioneApproccioPrestazioniCompromessi
isolated-vmIsolati V8 separati (heap V8 diverso)VeloceIn modalità di manutenzione; richiede aggiornamenti manuali di V8
Processo separato / WorkerThread child_process o Worker con permessi limitatiMedioMaggiore overhead IPC; i dati devono essere serializzati
Contenitori / VMDocker, gVisor, FirecrackerLentoOverhead di avvio; uso intensivo di risorse
Servizi gestitiEsecuzione di codice basata su cloud (es. AWS Lambda, Cloudflare Workers)VariabileLatenza di rete; dipendenza esterna