Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Outils/GitHubGitHub/patriksimek/vm2
Analyse Dynamique (Sandboxing)Analyse de CodeVirtualisation de SécuritéUtilitaires et Frameworks
GitHubpatriksimek/vm2

vm2

Sandbox JavaScript isolée pour Node.js qui exécute du code non fiable avec un accès restreint aux modules intégrés et aux ressources hôte via une interception basée sur Proxy.

Voir le dépôt
4.1k32626il y a 2 joursVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

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 est un bac à sable qui peut exécuter du code non fiable avec les modules intégrés de Node.js figurant sur la liste blanche.

Installation```sh

npm install vm2

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

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

Veuillez fournir le contenu Markdown à traduire.```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:~
## Avertissement de sécurité important

**Avant d'utiliser vm2, vous devez comprendre son fonctionnement et ses limites.**

vm2 tente de cloisonner du code JavaScript non fiable **dans le même processus Node.js** que votre application. Pour ce faire, il s'appuie sur un réseau complexe de [Proxies](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) qui interceptent et arbitrent chaque interaction entre le bac à sable et l'environnement hôte.

### Le défi fondamental

JavaScript est un langage extraordinairement dynamique. Les objets peuvent être atteints via les chaînes de prototypes, les constructeurs peuvent être atteints via les objets d'erreur, les symboles fournissent des hooks de protocole, et l'exécution asynchrone crée des fenêtres de timing. Le nombre considérable de façons de passer d'un objet à un autre en JavaScript rend la construction d'un bac à sable in-process hermétique extrêmement difficile.

**Nous sommes honnêtes à propos de cette réalité :** Malgré tous nos efforts, les chercheurs et les professionnels de la sécurité découvrent en permanence de nouvelles façons de s'échapper du bac à sable de vm2. Nous corrigeons activement ces vulnérabilités dès qu'elles sont signalées, mais la nature de jeu du chat et de la souris du cloisonnement in-process implique que :

1. **De nouvelles contournements seront probablement découverts à l'avenir.** Consultez nos [avis de sécurité](https://github.com/patriksimek/vm2/security/advisories) pour connaître les vulnérabilités connues.
2. **Vous devez maintenir vm2 à jour** pour bénéficier des derniers correctifs de sécurité. Abonnez-vous aux avis de sécurité et mettez à jour rapidement.
3. **vm2 ne doit pas être votre seule ligne de défense.** La défense en profondeur est essentielle lors de l'exécution de code non fiable.

### Alternatives plus robustes

Si vous avez besoin de garanties d'isolation plus fortes, envisagez ces alternatives qui offrent une **véritable isolation au niveau du processus ou du matériel** :

| Solution | Approche | Performance | Compromis |
|----------|----------|-------------|------------|
| **[isolated-vm](https://github.com/laverdet/isolated-vm)** | Isolats V8 séparés (tas V8 différent) | Rapide | En mode maintenance ; nécessite des mises à jour manuelles de V8 |
| **Processus séparé / Worker** | `child_process` ou threads Worker avec permissions limitées | Moyenne | Surcharge IPC plus élevée ; les données doivent être sérialisées |
| **Conteneurs / VM** | Docker, gVisor, Firecracker | Lente | Surcharge de démarrage ; gourmand en ressources |
| **Services gérés** | Exécution de code dans le cloud (par ex., AWS Lambda, Cloudflare Workers) | Variable | Latence réseau ; dépendance externe |

### Quand vm2 peut encore être approprié

vm2 peut convenir lorsque :
- Vous avez besoin d'une intégration étroite avec les objets hôtes et d'une communication synchrone rapide
- Le code non fiable provient d'une source relativement fiable (par ex., outils internes, systèmes de plugins avec des auteurs vérifiés)
- Vous combinez vm2 avec d'autres couches de sécurité (isolation réseau, restrictions du système de fichiers, limites de ressources)
- Vous acceptez le risque et surveillez activement les mises à jour de sécurité

**Si vous exécutez du code provenant de sources totalement non fiables (par ex., soumissions d'utilisateurs arbitraires), nous vous recommandons fortement d'utiliser une solution offrant des garanties d'isolation plus fortes.**

## Environnements d'exécution

| Environnement | Statut |
|---------|--------|
| Node.js | Pris en charge. Le bac à sable est une frontière de sécurité. |
| Bun | **Expérimental.** Compatibilité fonctionnelle partielle — **pas** une frontière de sécurité. |

Deux limitations distinctes s'appliquent à Bun, et aucune n'implique l'autre.

**Ce n'est pas une frontière de sécurité.** Le modèle de menace de vm2, le catalogue d'attaques dans
[`docs/ATTACKS.md`](https://github.com/patriksimek/vm2/blob/main/docs/ATTACKS.md), et chaque test de régression dans `test/ghsa/`
sont dérivés des mécanismes internes de V8. JavaScriptCore, que Bun utilise, a ses propres
équivalents, et aucun n'a été audité par rapport au pont de vm2. La suite qui passe
sous Bun démontre une compatibilité, pas que le bac à sable tient là-bas. **N'utilisez pas
vm2 sur Bun pour isoler du code non fiable.**

**La compatibilité est partielle, pas une parité.** Un passage vert sous Bun ne couvre que les tests
qui s'y exécutent réellement. `test/bun-skips.js` liste ce qui est exclu et pourquoi,
et les écarts de comportement connus incluent :

- `Buffer.from(arrayLike)` renvoie un buffer de longueur nulle
- Les métadonnées `filename` / `lineOffset` / `columnOffset` de `VMScript` ne sont pas
  observables, car les objets CallSite de JSC ne portent aucune méthode
- `Object.freeze` sur un objet hôte gelé avec un accesseur non configurable
  lève une `TypeError` d'invariant de proxy là où V8 ne le fait pas
- certaines opérations `Buffer` à travers la frontière du bac à sable sont considérablement plus lentes —
  un `allocUnsafe` de 64 Mo prend plus de 400 secondes contre 1,7 sur Node, assez lent
  pour être perçu comme un blocage

Considérez la prise en charge de Bun comme une compatibilité au mieux pour du code fiable, et vérifiez la
liste des exclusions avant de vous fier à un comportement particulier.

## Fonctionnalités

-   Exécute du code non fiable en toute sécurité dans un seul processus, en parallèle de votre code
-   Contrôle total de la sortie console du bac à sable
-   Le bac à sable a un accès limité aux méthodes du processus
-   Il est possible de requérir des modules (intégrés et externes) depuis le bac à sable
-   Vous pouvez limiter l'accès à certains (ou tous) modules intégrés
-   Vous pouvez appeler des méthodes en toute sécurité et échanger des données et des callbacks entre les bacs à sable
-   Maintenu activement avec des correctifs pour les méthodes d'évasion connues (voir [Avertissement de sécurité](#important-security-disclaimer))
-   Prise en charge du transpileur

## Comment cela fonctionne

-   Il utilise le module VM interne pour créer un contexte sécurisé.
-   Il utilise des [Proxies](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) pour empêcher l'évasion du bac à sable.
-   Il remplace le require intégré pour contrôler l'accès aux modules.

Pour un aperçu approfondi des mécanismes internes de vm2, voir [docs/ATTACKS.md](https://github.com/patriksimek/vm2/blob/main/docs/ATTACKS.md).

## Quelle est la différence entre le module vm de Node et vm2 ?

Essayez par vous-même :```js
import { runInNewContext } from "node:vm";

runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');
root@kitploit:~
## 🛡️ Fonctionnalités de sécurité

- **Authentification** : Authentification par jeton pour sécuriser l'accès à l'API.
- **Contrôle d'accès basé sur les rôles (RBAC)** : Permissions granulaires pour les utilisateurs et les rôles.
- **Journalisation d'audit** : Journalisation complète de toutes les actions et événements.
- **Chiffrement** : Chiffrement des données au repos et en transit à l'aide de normes industrielles.
- **Conformité** : Conforme aux normes et réglementations de sécurité courantes.

## 📦 Installation

Pour installer l'outil, exécutez la commande suivante :

```bash
pip install kitploit-tool

🚀 Démarrage rapide

Après l'installation, vous pouvez démarrer l'outil avec :

root@kitploit:~
kitploit-tool --help

Cela affichera toutes les options et commandes disponibles.

📚 Documentation

Une documentation détaillée est disponible dans le répertoire docs/. Elle comprend des guides d'installation, des tutoriels d'utilisation et des références API.

🤝 Contribution

Les contributions sont les bienvenues ! Veuillez consulter le fichier CONTRIBUTING.md pour plus de détails sur la façon de contribuer à ce projet.

📄 Licence

Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.

root@kitploit:~
import { VM } from 'vm2';

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

-   [VM](#vm)
-   [NodeVM](#nodevm)
-   [VMScript](#vmscript)
-   [Gestion des erreurs](#error-handling)
-   [Débogage d'un code sandboxé](#debugging-a-sandboxed-code)
-   [Objets en lecture seule](#read-only-objects-experimental)
-   [Objets protégés](#protected-objects-experimental)
-   [Relations entre sandbox](#cross-sandbox-relationships)
-   [CLI](#cli)
-   [Modifications de la 2.x à la 3.x](https://github.com/patriksimek/vm2/wiki/2.x-to-3.x-changes)
-   [Documentation 1.x et 2.x](https://github.com/patriksimek/vm2/wiki/1.x-and-2.x-docs)
-   [Contribution](https://github.com/patriksimek/vm2/wiki/Contributing)

## VM

VM est un sandbox simple permettant d'exécuter de manière synchrone du code non fiable sans la fonctionnalité `require`. Seuls les objets intégrés de JavaScript et le `Buffer` de Node sont disponibles. Les fonctions de planification (`setInterval`, `setTimeout` et `setImmediate`) ne sont pas disponibles par défaut.

**Options :**

-   `timeout` - Délai d'expiration du script en millisecondes. **AVERTISSEMENT** : Vous pourriez vouloir utiliser cette option avec `allowAsync=false`. De plus, manipuler les objets renvoyés par le sandbox peut exécuter du code arbitraire et contourner le délai d'expiration. Il convient de vérifier si l'objet renvoyé est une primitive avec `typeof` et de l'écarter complètement (la journalisation ou la création de messages d'erreur avec un tel objet peut également exécuter du code arbitraire) dans l'autre cas.
-   `sandbox` - Objet global du VM.
-   `compiler` - `javascript` (par défaut), `typescript`, `coffeescript` ou une fonction de compilation personnalisée. La bibliothèque s'attend à ce que le compilateur soit préinstallé si la valeur est définie sur `typescript` ou `coffeescript`. **`typescript` nécessite `typescript@6` ou une version antérieure** — voir [Compilateurs](#compilers).
-   `eval` - Si défini sur `false`, tout appel à `eval` ou aux constructeurs de fonctions (`Function`, `GeneratorFunction`, etc.) lèvera une `EvalError` (par défaut : `true`).
-   `wasm` - Si défini sur `false`, toute tentative de compilation d'un module WebAssembly lèvera une `WebAssembly.CompileError` (par défaut : `true`). Remarque : `WebAssembly.JSTag` est supprimé à l'intérieur du sandbox pour des raisons de sécurité, donc le code wasm ne peut pas intercepter les exceptions JavaScript.
-   `allowAsync` - Si défini sur `false`, toute tentative d'exécution de code utilisant `async` lèvera une `VMError` (par défaut : `true`).
-   `bufferAllocLimit` - Taille maximale en octets pour une seule requête `Buffer.alloc` / `Buffer.allocUnsafe` / `Buffer.allocUnsafeSlow` / `Buffer(N)` / `new Buffer(N)` depuis l'intérieur du sandbox. Les requêtes dépassant cette limite lèvent une `RangeError` de manière synchrone sans effectuer l'allocation hôte. Par défaut : `Infinity` (aucune limite, entièrement rétrocompatible). Les intégrateurs exécutant du code non fiable dans des environnements à mémoire contrainte (Docker / Kubernetes / Lambda / serverless) devraient opter pour une limite finie (par exemple `32 * 1024 * 1024`) dans le cadre d'une défense DoS en couches, de la même manière qu'ils optent pour `timeout`. Voir [Recommandations de durcissement](#hardening-recommendations) ci-dessous.

**IMPORTANT** : Le délai d'expiration n'est efficace que sur le code synchrone que vous exécutez via `run`. Le délai d'expiration ne fonctionne **PAS** sur les méthodes renvoyées par VM. Il existe certaines situations où le délai d'expiration ne fonctionne pas - voir [#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
```
Vous pouvez également récupérer des valeurs depuis la VM.```js
let number = vm.run('1337'); // returns 1337
```
**ASTUCE** : Consultez les tests pour plus d'exemples d'utilisation.

## NodeVM

Contrairement à `VM`, `NodeVM` vous permet d'utiliser `require` pour charger des modules de la même manière que dans le contexte Node standard.

**Options :**

-   `console` - `inherit` pour activer la console, `redirect` pour rediriger vers des événements, `off` pour désactiver la console (défaut : `inherit`).
-   `sandbox` - L'objet global de la VM.
-   `compiler` - `javascript` (défaut), `typescript`, `coffeescript` ou une fonction de compilation personnalisée (qui reçoit le code et son chemin de fichier). La bibliothèque s'attend à ce que le compilateur soit pré-installé si la valeur est définie sur `typescript` ou `coffeescript`. **`typescript` nécessite `typescript@6` ou une version antérieure** — voir [Compilateurs](#compilers).
-   `eval` - Si défini sur `false`, tout appel à `eval` ou aux constructeurs de fonctions (`Function`, `GeneratorFunction`, etc.) lèvera une `EvalError` (défaut : `true`).
-   `wasm` - Si défini sur `false`, toute tentative de compilation d'un module WebAssembly lèvera une `WebAssembly.CompileError` (défaut : `true`). Remarque : `WebAssembly.JSTag` est supprimé dans le sandbox pour des raisons de sécurité, donc le code wasm ne peut pas intercepter les exceptions JavaScript.
-   `bufferAllocLimit` - Même sémantique que sur `VM` — taille maximale en octets pour une seule requête de la famille `Buffer.alloc` depuis l'intérieur du sandbox. Défaut : `Infinity`. Voir [Recommandations de durcissement](#hardening-recommendations).
-   `sourceExtensions` - Tableau d'extensions de fichiers à traiter comme code source (défaut : `['js']`).
-   `require` - `true`, un objet ou un Resolver pour activer la méthode `require` (défaut : `false`).
-   `require.external` - Les valeurs peuvent être `true`, un tableau de modules externes autorisés, ou un objet (défaut : `false`). Tous les chemins correspondant à `/node_modules/${module_externe_autorisé_quelconque}/(?!/node_modules/)` sont autorisés à être requis.
-   `require.external.modules` - Tableau de modules externes autorisés. Prend également en charge les jokers, donc spécifier `['@scope/*-ver-??]`, par exemple, permettra d'utiliser tous les modules ayant un nom de la forme `@scope/something-ver-aa`, `@scope/other-ver-11`, etc. Le joker `*` ne correspond pas aux séparateurs de chemins.
-   `require.external.transitive` - Booléen indiquant si les dépendances transitives des modules externes sont autorisées (défaut : `false`). **AVERTISSEMENT** : Lorsqu'un module est requis de manière transitive, n'importe quel module peut alors le requérir normalement, même si cela n'était pas possible avant son chargement.
-   `require.builtin` - Tableau de modules intégrés autorisés, accepte ["\*"] pour tous (défaut : aucun). **AVERTISSEMENT** : "\*" peut être dangereux car de nouveaux modules intégrés peuvent être ajoutés.
-   `require.root` - Chemin(s) restreint(s) où les modules locaux peuvent être requis (défaut : tous les chemins).
-   `require.mock` - Collection de modules simulés (externes ou intégrés).
-   `require.context` - `host` (défaut) pour requérir les modules dans l'hôte et les proxifier dans le sandbox. `sandbox` pour charger, compiler et requérir les modules dans le sandbox. `callback(moduleFilename, ext)` pour choisir dynamiquement un contexte par module. Le défaut sera le sandbox si rien n'est spécifié. À l'exception de `events`, les modules intégrés sont toujours requis dans l'hôte et proxifiés dans le sandbox.
-   `require.import` - Tableau de modules à charger dans NodeVM au démarrage.
-   `require.resolve` - Fonction de recherche supplémentaire au cas où un module ne serait pas trouvé dans les chemins de recherche Node traditionnels.
-   `require.customRequire` - À utiliser à la place de la fonction `require` pour charger des modules depuis l'hôte.
-   `require.strict` - `false` pour ne pas forcer le mode strict sur les modules chargés par require (défaut : `true`).
-   `require.fs` - Implémentation personnalisée du système de fichiers.
-   `nesting` - **AVERTISSEMENT** : Autoriser cela est un risque de sécurité car les scripts peuvent créer une NodeVM qui peut requérir n'importe quel module hôte. `true` pour activer l'imbrication des VM (défaut : `false`).
-   `wrapper` - `commonjs` (défaut) pour envelopper le script dans un wrapper CommonJS, `none` pour récupérer la valeur retournée par le script.
-   `argv` - Tableau à passer à `process.argv`.
-   `env` - Objet à passer à `process.env`.
-   `strict` - `true` pour charger les modules en mode strict (défaut : `false`).

**IMPORTANT** : Le délai d'expiration n'est pas effectif pour NodeVM, il n'est donc pas immunisé contre `while (true) {}` ou des malveillances similaires.

**RAPPELEZ-VOUS** : Plus vous autorisez de modules, plus votre sandbox devient 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);
});
```
Lorsque `wrapper` est défini sur `none`, `NodeVM` se comporte davantage comme `VM` pour le code synchrone.```js
assert.ok(vm.run('return true') === true);
```
**ASTUCE** : Consultez les tests pour plus d'exemples d'utilisation.

### Chargement de modules par chemin relatif

Pour charger des modules par chemin relatif, vous devez passer le chemin complet du script que vous exécutez comme deuxième argument à la méthode `run` de vm si le script est une chaîne de caractères. Le nom de fichier est alors affiché dans toutes les traces de pile générées par le script.```js
vm.run('require("foobar")', '/data/myvmscript.js');
```
Si le script que vous exécutez est un VMScript, le chemin est fourni dans le constructeur VMScript.```js
const script = new VMScript('require("foobar")', { filename: '/data/myvmscript.js' });
vm.run(script);
```
### Resolver

Un resolver peut être créé via `makeResolverFromLegacyOptions` et être utilisé pour plusieurs instances `NodeVM`, permettant de partager le code de module compilé et potentiellement d'accélérer les temps de chargement. Le premier exemple de `NodeVM` peut être réécrit en utilisant `makeResolverFromLegacyOptions` comme suit.```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

Vous pouvez améliorer les performances en utilisant des scripts précompilés. Le VMScript précompilé peut être exécuté plusieurs fois. Il est important de noter que le code n'est lié à aucune VM (contexte) ; il est plutôt lié avant chaque exécution, uniquement pour cette exécution.```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));
```
Ça fonctionne à la fois pour `VM` et `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));
```
Le code est compilé automatiquement la première fois qu'il est exécuté. On peut compiler le code à tout moment avec `script.compile()`. Une fois le code compilé, la méthode n'a aucun effet.

## Compilateurs

`compiler` accepte `javascript` (par défaut), `typescript`, `coffeescript`, ou votre propre fonction. Les compilateurs `typescript` et `coffeescript` sont optionnels — installez le paquet vous-même ; vm2 ne dépend d'aucun des deux.

### TypeScript

**Le compilateur `typescript` intégré nécessite `typescript@6` ou une version antérieure.**

vm2 transpile via l'API `transpileModule()` de TypeScript. TypeScript 7 l'a retirée du point d'entrée du paquet — `require('typescript')` y résout uniquement vers `{ version, versionMajorMinor }`, et l'API de remplacement se trouve derrière les sous-chemins explicitement instables `typescript/unstable/*`, dont aucun ne fournit d'équivalent de transpilation en un seul fichier. Il n'y a donc rien sur lequel vm2 puisse se rabattre sur la version 7.x.

Sélectionner `compiler: 'typescript'` avec TypeScript 7 installé lève une exception à `new VMScript(...)` / `new VM(...)` :```
VMError: The installed TypeScript (7.0.2) does not expose the transpileModule() API that
vm2's built-in TypeScript compiler uses; it was removed from the package entry point in
TypeScript 7. Install typescript@6 or earlier, or pass your own transpiler as a function:
{ compiler: (code, filename) => javaScriptSource }.
```
Soit épingler `typescript@6`, soit fournir votre propre transpileur — toute fonction renvoyant du JavaScript fonctionne, donc le `tsc` de TypeScript 7, esbuild, swc, ou un type-stripper sont tous valides :```js
import { VM, VMScript } from 'vm2';
import { transformSync } from 'esbuild';

const script = new VMScript('const x: number = 1; x', {
	compiler: (code, filename) => transformSync(code, { loader: 'ts', format: 'cjs' }).code,
});

new VM().run(script);
```
Un compilateur personnalisé reçoit `(code, filename)` et doit renvoyer du code source JavaScript. Il s'exécute **dans le domaine hôte, avant le sandboxing** — traitez-le comme du code de confiance et n'en construisez jamais un à partir d'une entrée non fiable.

### CoffeeScript

Nécessite que `coffee-script` soit installé. Compilé avec `{ header: false, bare: true }` ; toutes les `compilerOptions` que vous transmettez sont fusionnées par-dessus celles-ci.

## Gestion des erreurs

Les erreurs dans la compilation du code et l'exécution synchrone du code peuvent être gérées par `try-catch`. Les erreurs dans l'exécution asynchrone du code peuvent être gérées en attachant un gestionnaire d'événement `uncaughtException` au `process` de 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);
});
```
## Débogage d'un code sandboxé

Vous pouvez déboguer ou inspecter le code s'exécutant dans le sandbox comme s'il s'exécutait dans un processus normal.

-   Vous pouvez utiliser des points d'arrêt (ce qui nécessite de spécifier un nom de fichier de script)
-   Vous pouvez utiliser le mot-clé `debugger`.
-   Vous pouvez utiliser l'option step-in pour entrer dans le code s'exécutant dans le sandbox.

### Exemple

/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;
```
## Objets en lecture seule (expérimental)

Pour empêcher les scripts sandboxés d'ajouter, de modifier ou de supprimer des propriétés des objets proxifiés, vous pouvez utiliser les méthodes `freeze` pour rendre l'objet en lecture seule. Cela n'est efficace qu'à l'intérieur de la VM. Les objets figés sont affectés en profondeur. Les types primitifs ne peuvent pas être figés.

**Exemple sans utiliser `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
```
**Exemple avec utilisation de `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
```
**IMPORTANT :** Il n'est pas possible de geler des objets qui ont déjà été proxifiés vers la VM.

## Objets protégés (expérimental)

Contrairement à `freeze`, cette méthode permet aux scripts sandboxés d'ajouter, de modifier ou de supprimer des propriétés sur des objets, à une exception près : il n'est pas possible d'attacher des fonctions. Les scripts sandboxés ne peuvent donc pas modifier des méthodes comme `toJSON`, `toString` ou `inspect`.

**IMPORTANT :** Il n'est pas possible de protéger des objets qui ont déjà été proxifiés vers la VM.

## Relations inter-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

Avant de pouvoir utiliser vm2 en ligne de commande, installez-le globalement avec `npm install vm2 -g`.```sh
vm2 ./script.js
```
## Recommandations de durcissement

vm2 empêche les évasions de sandbox (code non fiable obtenant un accès au realm hôte). Il ne prévient **pas**, à lui seul, toutes les formes d'épuisement des ressources ou de déni de service. Les intégrateurs exécutant du code non fiable devraient ajouter les défenses en couches suivantes autour de la sandbox.

### 1. Limiter l'allocation mémoire avec `bufferAllocLimit`

Un simple appel `Buffer.alloc(N)` avec un `N` contrôlé par l'attaquant s'exécute comme une allocation C++ hôte synchrone que le `timeout` de V8 ne peut pas interrompre. Dans les environnements à mémoire limitée, une charge utile de sandbox d'environ 100 octets peut provoquer un saut de RSS hôte de plus de 100 Mo et faire planter le processus hôte via un OOM. Définissez `bufferAllocLimit` (par ex. `32 * 1024 * 1024`) pour plafonner les allocations individuelles :```js
const vm = new VM({
	timeout: 1000,
	bufferAllocLimit: 32 * 1024 * 1024,
	allowAsync: false,
});
```
La limite s'applique également aux chemins obsolètes `Buffer(N)` et `new Buffer(N)`. Notez que l'épuisement agrégé (nombreuses petites allocations, `Buffer.concat`, `Uint8Array`, `String.repeat`, `Array(n).fill()`, etc.) n'est **pas** couvert par cette limite — combinez-la avec une limite mémoire côté hôte (`--max-old-space-size`, limite de conteneur, cgroup) pour une couverture complète.

### 2. Installer un gestionnaire `unhandledRejection` côté hôte

Il existe une classe de DoS par abandon du processus hôte où le code sandbox crée une `async function`, une `async function*` ou un `await using` dont le corps lève une valeur qui déclenche une erreur du domaine hôte lors du formatage de la pile (par exemple `e.name = Symbol(); e.stack`). V8 crée la promesse de rejet via la promesse intrinsèque du domaine, ce qui contourne le sous-classement `Promise` de vm2, de sorte que le rejet s'échappe vers l'hôte en tant que `unhandledRejection`. Sur Node 15+, le comportement par défaut est de terminer le processus.

Fermer cette faille nécessite de modifier le comportement observable de l'hôte, donc vm2 ne fournit pas de correctif par défaut. Les intégrateurs doivent installer un gestionnaire au niveau du processus qui avale (ou journalise) les rejets provenant du 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);
});
```
Si votre application n'a aucune autre source de rejets non gérés, une absorption globale + journalisation est acceptable :```js
process.on('unhandledRejection', reason => {
	yourLogger.warn('swallowed sandbox rejection', reason);
});
```
### 3. Exécution avec une limite de mémoire au niveau du processus

Même avec `bufferAllocLimit` défini, exécutez le processus hôte avec `--max-old-space-size` (ou une limite de mémoire de conteneur équivalente) adaptée à la charge de travail. La limite protège contre la primitive d'allocation unique ; la limite au niveau du système d'exploitation protège contre l'épuisement agrégé et contre toute future primitive d'allocation que vm2 n'a pas encore plafonnée.

### 4. Traitez `require.builtin: ['*']` comme une configuration hors sandbox

Le caractère générique `'*'` s'étend à la plupart des modules intégrés de Node, notamment `child_process`, `fs`, `dgram`, `net`, `http` et `dns`. Ce sont des primitives à pleine capacité de l'hôte — `require('child_process').execSync('id')` est accessible depuis la sandbox sous `'*'`. La sémantique de `'*'` de vm2 est intentionnelle (certains intégrateurs exécutent du code de confiance mais isolé), mais elle ne doit pas être utilisée par défaut pour du code non fiable. Privilégiez une liste blanche explicite du plus petit ensemble de modules dont votre sandbox a réellement besoin.

### 5. `nesting: true` est une porte de sortie

`nesting: true` permet au code de la sandbox d'utiliser `require('vm2')` et de construire des NodeVM imbriquées. **La configuration `require` de la VM imbriquée est choisie par le code de la sandbox qui la construit, et non contrainte par la VM externe.** Concrètement :```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
`);
```
Si vous définissez `nesting: true`, vous accordez en pratique au sandbox le même niveau de confiance que vous avez. **N'activez pas `nesting: true` pour du code non fiable.** Utilisez-le uniquement lorsque vous faites confiance au code sandboxé lui-même, mais que vous souhaitez une sémantique d'exécution de type VM (global frais, timeouts contrôlés) pour des raisons non liées à la sécurité.

`nesting: true` **exige un objet de configuration `require` explicite** (par ex. `require: { builtin: [] }` ou `require: {}`). Toute autre forme — `require: false`, `require: undefined`, `require: null`, ou l'omission complète de `require` — lève une `VMError` à la construction (GHSA-m4wx-m65x-ghrr, remplace GHSA-8hg8-63c5-gwmx). Toutes ces formes produisent un résolveur de type NESTING_OVERRIDE uniquement : le sandbox peut `require('vm2')` mais rien d'autre, ce qui constitue une primitive d'évasion pure sans usage légitime. Pour refuser tous les requires, supprimez `nesting: true`. Pour autoriser des VM imbriquées, fournissez une configuration `require` explicite afin que le compromis soit visible au niveau du site d'appel.

## Problèmes connus

-   Il n'est pas possible de définir une classe qui étend une classe proxifiée. Cela inclut l'utilisation d'une classe proxifiée dans `Object.create`.
-   L'évaluation directe (`eval`) ne fonctionne pas.
-   La journalisation des tableaux du sandbox répétera la partie tableau dans les propriétés.
-   Les transformations du code source peuvent produire une chaîne source différente pour une fonction.
-   Il existe des moyens de faire planter le processus node depuis l'intérieur du sandbox. Voir [Recommandations de durcissement](#hardening-recommendations).
-   Le compilateur `typescript` intégré ne fonctionne pas avec TypeScript 7 ou plus récent, qui a supprimé l'API `transpileModule()` utilisée par vm2. Utilisez `typescript@6` ou fournissez votre propre transpileur — voir [Compilateurs](#compilers).

[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
Télécharger l’outil