Guide

Node2Shell : la faille Brotli de Node.js, qui est exposé et comment la corriger

Node2Shell est le nom que les chercheurs ont donné à CVE-2026-111497, une faille du décodeur Brotli intégré à Node.js. Le 21 octobre 2026, le projet Node.js l'a corrigée dans 22.23.4, 24.22.1 et 26.12.1. Une application qui décompresse des données Brotli fournies par quelqu'un d'autre, comme le corps compressé d'une requête ou une réponse récupérée sur un autre serveur, peut planter, laisser fuiter de la mémoire ou exécuter le code d'un attaquant. Le correctif est dans Node.js lui-même, donc `npm update` ne l'applique pas : il faut mettre à jour le runtime partout où il tourne.

Ce qu'est Node2Shell

Brotli est un format de compression que les serveurs web et les navigateurs utilisent à côté de gzip. Node.js intègre un décodeur Brotli dans `node:zlib`. L'avis de Node.js décrit le bug : un changement de bloc invalide dans un flux compressé était traité comme un besoin temporaire de données supplémentaires au lieu d'une erreur de format, si bien que le décodeur continuait d'ajouter des octets à un tampon interne de huit octets et écrivait au-delà de sa fin. Une telle corruption de mémoire peut faire planter le processus, laisser fuiter de la mémoire ou permettre à un attaquant d'exécuter du code.

Node.js la classe comme élevée et indique qu'elle permet l'exécution de code à distance. Elle a été signalée par OpenAI Codex Security. Les chercheurs d'Imperva l'ont ensuite reproduite comme exécution de code sans authentification, et un code de preuve de concept est public : considérez donc chaque service Node.js non corrigé qui traite des données externes comme une cible.

Êtes-vous exposé ?

Un processus Node.js est exposé lorsque lui-même, ou une bibliothèque qu'il utilise, décompresse des données Brotli contrôlées par un attaquant. Imperva a testé deux cas courants.

**Requêtes entrantes.** Express 5 et body-parser 2 décompressent les corps de requête envoyés avec `Content-Encoding: br`, car l'option `inflate` de body-parser est activée par défaut. Une application avec `app.use(express.json())` est donc atteignable par une seule requête piégée, avant toute connexion.

**Requêtes sortantes.** Le `fetch()` intégré de Node demande et décompresse lui-même les réponses Brotli. Tout serveur que votre code appelle et qu'un attaquant contrôle ou a compromis atteint le décodeur : webhooks que vous rappelez, aperçus de liens, scrapers, agents IA qui récupèrent les pages qu'un utilisateur leur donne, contrôles de santé d'autres sites.

Le code qui appelle directement les fonctions Brotli de `node:zlib` sur des données externes est exposé de la même façon. Les pare-feu placés devant votre application ne voient que le premier cas : ils ne peuvent pas inspecter ce que votre code récupère ailleurs.

Quelles versions corrigent la faille

Chaque branche de Node.js prise en charge a une version avec le correctif (voir le tableau). La même version corrige neuf autres vulnérabilités, dont trois bugs de certificats TLS et de DNS classés élevés : elle vaut donc la peine même si votre application n'utilise jamais Brotli.

Node.js 20 et les versions antérieures ne reçoivent pas de correctif : elles sont en fin de vie, et le projet Node.js indique que les versions en fin de vie sont toujours concernées lorsqu'une version de sécurité sort. Bun, qui intègre son propre décodeur Brotli, a corrigé la même faille dans 1.4.4.

Où se cache Node.js

La mise à jour doit atteindre chaque copie de Node qui exécute votre code, et il y en a généralement plusieurs.

**Images de conteneur.** Un Dockerfile figé sur une version exacte, comme `node:24.22.0`, reste vulnérable quel que soit le nombre de reconstructions : passez à 24.22.1 ou plus récent. Les images de base qui embarquent leur propre Node (par exemple les images de tests navigateur) figent la version en vigueur lors de leur construction : mettez donc Node à jour à l'intérieur aussi.

**Serveurs et CI.** Node installé avec nvm, un gestionnaire de paquets ou une action de configuration de CI se met à jour à cet endroit, puis on redémarre le service.

**Plateformes d'hébergement.** Vercel a déployé le 21 octobre des règles de pare-feu contre le cas entrant pour tous les projets et gère les versions de correctif de ses runtimes Node.js 22.x et 24.x : ces projets n'ont pas besoin de changer de version. Les projets encore sur Node.js 20 doivent passer à 22.x ou 24.x et redéployer. Vercel précise aussi que son pare-feu ne couvre pas les réponses que vos fonctions récupèrent sur d'autres serveurs. Chez les autres hébergeurs, consultez l'avis de la plateforme pour savoir quelle version de Node exécute vos fonctions.

**Applications créées avec l'IA.** Si un générateur d'applications IA ou un agent de code a écrit le code serveur de votre application, la question est la même : quel runtime l'exécute, et en quelle version. La page surveillance des apps créées par IA explique quoi surveiller d'autre une fois en ligne.

Comment vérifier

Lancez `node --version` sur les portables, les runners de CI et les serveurs, et `docker run --rm <image> node --version` pour chaque image de conteneur. Dans un service en cours d'exécution, vous pouvez journaliser `process.version` au démarrage. Tout ce qui est en dessous de la version corrigée de sa branche, ou sur Node.js 20 et antérieur, doit être mis à jour.

Si vous ne pouvez pas mettre à jour aujourd'hui

La mise à jour est la solution. En attendant son déploiement, vous pouvez réduire le cas entrant : refusez les requêtes avec `Content-Encoding: br` au niveau de votre proxy ou pare-feu, ou mettez `inflate: false` sur body-parser et `express.json()`, ce qui rejette tout corps de requête compressé (vérifiez d'abord qu'aucun de vos clients n'en envoie).

Aucun réglage ne protège le cas sortant, car un serveur malveillant peut envoyer une réponse Brotli quoi que demande votre code. Évitez de récupérer des URL non fiables depuis des services non corrigés tant qu'ils ne sont pas à jour.

Comment Relvato aide

Relvato ne peut pas lire de l'extérieur la version de Node.js d'un site, et n'envoie pas de requêtes de type attaque pour la découvrir : il ne signale donc pas Node2Shell directement.

Ce qu'il fait : l'analyse d'exposition signale un en-tête `X-Powered-By: Express`, qui révèle votre stack à n'importe quel scanner (`app.disable("x-powered-by")` le supprime). Et mettre Node à jour est un changement comme un autre : avec les vérifications de déploiement depuis GitHub, Relvato relance vos moniteurs après le déploiement, pour que vous sachiez que la connexion, le paiement et vos pages clés fonctionnent toujours avec le nouveau runtime.

Relvato tourne aussi sur Node.js. Ses moniteurs récupèrent des pages sur les sites qu'ils surveillent, nous les avons donc passés à Node 24.22.1 la semaine de la sortie du correctif.

Runtimes avec le correctif Node2Shell

RuntimeCorrigé dansRemarque
Node.js 2626.12.1Branche actuelle
Node.js 2424.22.1LTS
Node.js 2222.23.4LTS
Node.js 20 et antérieuresPas de correctifFin de vie : passez à 22 ou 24
Bun1.4.4Intègre son propre décodeur Brotli

Questions fréquentes

npm update corrige-t-il Node2Shell ?

Non. La faille est dans Node.js lui-même, pas dans un paquet : mettre à jour les dépendances n'y change rien. Mettez le runtime Node.js à jour vers 22.23.4, 24.22.1 ou 26.12.1 ou plus récent partout où votre code tourne, puis redémarrez ou redéployez.

Je n'utilise pas Express. Suis-je protégé ?

Pas forcément. Le fetch() intégré de Node décompresse les réponses Brotli par défaut : le code qui récupère des données sur des serveurs que vous ne contrôlez pas est exposé, quel que soit le framework. Mettez Node à jour quand même.

Mon application est sur Vercel. Dois-je faire quelque chose ?

Sur Node.js 22.x ou 24.x, Vercel gère la version de correctif et applique des règles de pare-feu contre les corps de requête piégés : aucun changement de version n'est nécessaire. Sur Node.js 20, passez à 22.x ou 24.x et redéployez. Le pare-feu de Vercel ne couvre pas les réponses que vos fonctions récupèrent sur d'autres serveurs.

J'utilise Node.js 20 ou 18. Que faire ?

Elles ne reçoivent pas de correctif : les deux sont en fin de vie. Passez à Node.js 22 ou 24, testez et redéployez.

Un pare-feu applicatif web me protège-t-il ?

Seulement contre les requêtes piégées entrantes. Il ne voit pas les réponses que votre code récupère sur d'autres serveurs, qui sont l'autre point d'entrée. Les règles font gagner du temps ; la solution est la mise à jour.

Sources

À lire aussi
Guide

Sachez que votre application fonctionne toujours après chaque mise à jour.

Relvato relance vos moniteurs après chaque déploiement et mise à jour, de la connexion au paiement, pour qu'une mise à jour du runtime qui casse quelque chose se voie avant que vos utilisateurs ne la découvrent.