Votre version de Node.js est-elle vulnérable à la faille RCE Brotli ? Vérifiez en 2 minutes

La CVE-2026-111497 est une faille activement exploitée touchant le décodeur Brotli de Node.js. Vérifiez votre version en deux minutes, découvrez quels frameworks et clients HTTP sollicitent le décodeur, appliquez le correctif selon votre méthode d'installation et mettez en place des mesures...

Ashley Innocent

Ashley Innocent

5 November 2026

Votre version de Node.js est-elle vulnérable à la faille RCE Brotli ? Vérifiez en 2 minutes

Apidog pour les entreprises

Déploiement sur site

SSO & RBAC

Conforme SOC 2

Découvrir Apidog Enterprise

Exécutez cette commande sans attendre. Si votre version est inférieure au seuil minimal indiqué dans le tableau, vous êtes vulnérable à la RCE Brotli de Node.js (CVE-2026-111497), et des attaquants l'exploitent déjà activement.

node -v
Branche Vulnérable Corrigée à partir de Dernière version (5 nov. 2026)
26.x Inférieure à 26.12.1 26.12.1 26.13.0
24.x Inférieure à 24.22.1 24.22.1 24.22.2
22.x Inférieure à 22.23.4 22.23.4 22.23.4
25.x, 20.x et antérieures En fin de vie (EOL) : non corrigée et non évaluée Aucun correctif disponible Migrer vers la 24 ou la 26

Pour une seconde vérification, interrogez directement le binaire :

node -p "require('node:zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"

Le correctif a introduit cette constante. Nous avons testé cette commande sur neuf builds macOS officiels issus des trois branches supportées : chaque version corrigée a renvoyé -17, tandis que chaque ancienne version a renvoyé undefined. Fiez-vous d'abord à node -v, car une distribution Linux qui rétroporte le correctif pourrait ne pas inclure cette constante.

Ne vous fiez pas à process.versions.brotli. Cette commande a renvoyé 1.2.0 aussi bien sur la 24.21.0 que sur la 24.22.1, et 1.1.0 sur la 22.23.3 comme sur la 22.23.4. Node.js a intégré le correctif par cherry-pick sans incrémenter le numéro de version affiché ; ce champ ne permet donc pas de savoir si votre environnement est sécurisé.

En résumé

Question Réponse
De quoi s'agit-il ? Écriture hors limites (out-of-bounds write) dans le décodeur Brotli intégré à Node.js, également baptisée Node2Shell ou HTTP2Shell
Impact Plantage (crash), fuite de mémoire ou exécution de code à distance (RCE)
Sévérité HIGH (ÉLEVÉE) selon Node.js ; 9.8 CRITICAL (CRITIQUE, CVSS 3.1) selon le NVD
Exploitation active ? Oui. Le catalogue KEV de la CISA l'a répertoriée le 27 octobre 2026
Authentification requise ? Non, d'après le vecteur du NVD et l'analyse d'Akamai
Qui est exposé ? Toute application décodant des flux Brotli non maîtrisés : corps de requêtes dans Express 5, réponses fetch(), appels directs à node:zlib
Solution Mettre à niveau le runtime, reconstruire les images de conteneur, redémarrer les processus
Contournement ? Le bulletin de sécurité n'en mentionne aucun. Les mesures d'atténuation temporaires ci-dessous réduisent l'exposition sans pour autant tout couvrir
Timeline of CVE-2026-111497: Node.js fixes on October 21, CVE published October 22, exploit traffic reported October 26, CISA KEV listing October 27, KEV due date November 10, next Node.js security release November 11

ELLIO a signalé du trafic d'exploitation sur ses sondes dès le 26 octobre, soit cinq jours après la sortie du correctif. La charge utile (payload) interceptée ciblait Node.js 24.22.0 sur architecture x86-64. Si l'étape finale de ce payload a échoué lors des tests menés par ELLIO, l'équipe a toutefois confirmé avoir réussi à exécuter du code sur des builds 24.22.0 standards. La CISA a accordé aux agences fédérales américaines jusqu'au 10 novembre pour intervenir, et indique que l'utilisation par des ransomwares est « Inconnue ». Selon la télémétrie d'Akamai, 61 % des réseaux utilisaient encore des versions vulnérables au 26 octobre.

Comprendre Node2Shell : fonctionnement de la faille Brotli

Node2Shell est une vulnérabilité d'écriture hors limites (out-of-bounds write) située dans le décodeur Brotli intégré au runtime Node.js. Un flux compressé malformé amène le décodeur à écrire au-delà d'un tampon interne de huit octets, corrompant ainsi la mémoire du processus. Cela peut entraîner un plantage, une fuite de mémoire ou l'exécution arbitraire de code sous le contrôle d'un attaquant sur votre serveur.

La cause fondamentale réside dans une mauvaise classification d'erreur. Une commutation de bloc (block switch) invalide a été interprétée comme « données supplémentaires requises » au lieu de « données corrompues », incitant le décodeur en flux continu à continuer d'ajouter des octets dans ce petit tampon.

Cette faille provient de la bibliothèque Brotli de Google (versions 1.0.3 à 1.2.0) et ne se limite donc pas à Node.js. Node.js a corrigé sa propre copie en intégrant par cherry-pick le commit amont 0ed4268a dans la version 24.22.1 et les versions associées. Les chercheurs Khai Tran et Sylvie Mayer d'OpenAI Codex Security en sont à l'origine du signalement.

Vos scanners de dépendances ne détecteront pas cette vulnérabilité, car le décodeur est intégré directement au runtime et ne provient pas d'un paquet tiers. La commande npm install n'a signalé aucune vulnérabilité (0 vulnerability) sur notre projet de test Express 5 exécuté sur une version non corrigée de Node.js (24.15.0).

Qui est exposé ?

Avoir un runtime vulnérable ne suffit pas à lui seul : encore faut-il qu'il existe un chemin transmettant des données Brotli non fiables au décodeur. Nous avons testé chaque vecteur sous Node.js 24.22.1 en envoyant un corps de requête invalide mais inoffensif (le texte not-valid-brotli) avec l'en-tête Content-Encoding: br, ainsi qu'en fournissant du contenu Brotli valide à chaque client.

Vecteur / Chemin Version testée Décodeur exécuté ? Résultat observé
Express 5 express.json() 5.3.0 (body-parser 2.4.0) Oui, par défaut 400, « Decompression failed »
Express 4 express.json() 4.22.3 (body-parser 1.20.9) Non 415, encodage non supporté
Koa @koa/bodyparser 6.1.0 Oui, par défaut 500, erreur BrotliDecoder dans les logs
Fastify avec @fastify/compress 9.3.0 Oui, une fois enregistré 400, FST_CP_ERR_INVALID_CONTENT
Fastify standard 5.12.8 Non 400, JSON invalide
Serveur node:http brut ou http.get 24.22.1 Non Les octets bruts sont transmis tels quels
fetch() natif 24.22.1 Oui, toujours Décodage de la réponse
axios, got, node-fetch 1.21.0, 16.2.0, 3.3.2 Oui, par défaut Décodage de la réponse
zlib.brotliDecompress*, createBrotliDecompress Toutes Oui Il s'agit de l'API du décodeur
Diagram of paths into the Brotli decoder in node:zlib: Express 5 parsers, Koa body parsers and Fastify with @fastify/compress on the inbound side, fetch, axios and got on the outbound side, while Express 4, plain Fastify and bare node:http do not reach it

Deux résultats méritent une attention particulière. fetch() a décodé le flux Brotli même lorsque la requête spécifiait Accept-Encoding: identity, car il se conforme à l'en-tête de la réponse et non à ce qui a été demandé. N'importe quel serveur contacté par votre application peut donc solliciter le décodeur ; les outils de test de webhooks, les générateurs d'aperçu de liens ou les importateurs d'URL sont donc particulièrement exposés. Par ailleurs, un code 400 à lui seul ne prouve rien : Express 5 et Fastify standard renvoient tous deux une erreur 400, mais seul Express 5 a réellement exécuté le décodeur. Examinez attentivement le message d'erreur.

Identifiez vos surfaces d'exposition à l'aide de ces trois commandes :

# Direct decoder use
grep -rnE "brotliDecompress|createBrotliDecompress" src/

# Parsers that decode request bodies
npm ls express body-parser @koa/bodyparser @fastify/compress

# Base images and pinned versions
grep -rnE "^FROM .*node" --include='Dockerfile*' .

Il suffit d'un seul nouvel appel à fetch() pour changer la donne : même si vous vous pensez « non exposé », la mise à jour reste indispensable.

Comment corriger la CVE-2026-111497

Passez directement à la version la plus récente de votre branche, et non pas simplement à la version minimale requise. Au 5 novembre, toutes ces sources proposaient des builds corrigés :

Méthode d'installation Action à mener
nvm nvm install 24 && nvm alias default 24
Homebrew brew upgrade node (ou node@24, node@22)
Docker FROM node:24.22.2-slim, puis docker build --pull
Paquets de distribution Linux Consultez les avis de sécurité de votre distribution, car le correctif peut avoir été rétroporté sous un numéro de version antérieur
CI Mettez à jour .nvmrc, engines et node-version, puis relancez le build
Serverless Affichez process.version dans les logs d'une fonction déployée ; ne partez pas du principe que la plateforme l'a mise à jour automatiquement

Veillez ensuite à combler les deux angles morts qui piègent le plus souvent les équipes :

Terminez en exécutant les vérifications mentionnées au début de cet article directement dans le conteneur déployé, puis sur les exécuteurs CI et les postes de développement. Pour afficher la build de sécurité la plus récente pour chaque branche :

curl -s https://nodejs.org/dist/index.json | jq -r '[.[] | select(.security == true and (.version | test("^v(22|24|26)\\.")))] | group_by(.version | split(".")[0]) | .[] | max_by(.date) | "\(.version)  \(.date)"'

Vous utilisez encore la version 20 ou 25 ? Aucun build n'existe pour vous. Consultez le calendrier de fin de vie de Node.js 20 et migrez sans attendre.

Mesures d'atténuation si vous ne pouvez pas appliquer le correctif aujourd'hui

Ces solutions permettent de gagner du temps, mais aucune ne remplace une véritable mise à niveau.

  1. Rejetez br à la périphérie (edge). Bloquez Content-Encoding: br au niveau de votre proxy inverse ou de votre répartiteur de charge (load balancer), en effectuant une correspondance insensible à la casse et au sein de listes comme gzip, br.
  2. Rejetez-le au niveau de l'application. Placez ce middleware en amont de vos analyseurs de corps de requête (body parsers). Il a renvoyé un code 415 lors de notre test avec Express 5 :
app.use((req, res, next) => {
  const encoding = req.headers['content-encoding'] || '';
  if (/\bbr\b/i.test(encoding)) return res.status(415).end();
  next();
});
  1. Désactivez la décompression automatique. L'option express.json({ inflate: false }) a renvoyé une erreur 415 pour la même requête. Attention : cela rejette également les corps compressés en gzip, assurez-vous donc au préalable de la compatibilité avec vos clients.
  2. Contrôlez les réponses sortantes. axios accepte le paramètre decompress: false, ce qui a permis de conserver les octets non décodés lors de notre test. fetch() n'offre aucun mécanisme standard de désactivation ; limitez donc les hôtes qu'il peut contacter à l'aide d'une liste blanche et de règles de filtrage en sortie (egress).
  3. Limitez le rayon d'impact. Segmentez vos services Node.js et restreignez l'accès en lecture aux fichiers d'image mémoire (core dumps), car ELLIO souligne que les plantages peuvent y divulguer des données résidant en mémoire.

Surveillez les signes précurseurs détectés par ELLIO : des vagues de requêtes encodées en Brotli visant à identifier quels serveurs les décompressent. L'apparition inhabituelle de trafic avec Content-Encoding: br sur une API JSON ou une hausse anormale des plantages de workers justifie une enquête immédiate.

Vérifiez que votre API fonctionne toujours après la mise à niveau : confiez les tests à votre agent

Le passage à une nouvelle version majeure du runtime peut modifier le comportement de TLS, du DNS et de HTTP, et la mise à jour d'octobre a justement touché à ces trois aspects. Ne vérifiez pas ces écarts manuellement. Laissez votre agent de développement exécuter Apidog CLI avant et après la mise à niveau, puis vous signaler tout changement de comportement.

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com   # pick your agent when prompted

Transmettez ce prompt à votre agent :

Run Apidog test suite <id> in project <id> against staging and save the
results to reports/before. After I upgrade Node.js, add a test case for
POST /orders that sends the plain text "not-valid-brotli" with
Content-Encoding: br, asserts a 4xx status, then checks GET /health
returns 200. Rerun the suite to reports/after and list every request
whose result changed.

L'agent exécute ensuite les commandes suivantes :

apidog run --test-suite <id> --project <id> -e <envId> -r cli,junit --out-dir reports/before
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <id> --file case.json
apidog run --test-case <caseId> --project <id> -e <envId> -r cli,json
apidog run --test-suite <id> --project <id> -e <envId> -r cli,junit --out-dir reports/after

Ce cas de test supplémentaire sert de test de santé (health check) et non d'exploit : le corps envoyé est du texte brut, et il a échoué avec la même erreur de padding sur les versions vulnérables et corrigées lors de nos essais. Il révèle cependant une véritable lacune opérationnelle : notre test Koa a renvoyé un code 500 car l'erreur de décodage n'était pas interceptée, alors qu'une API publique devrait renvoyer une erreur 4xx. N'exécutez ce test que sur un environnement de préproduction (staging).

La documentation de référence de la commande run détaille l'ensemble des options disponibles, et le guide CI/CD vous montre comment intégrer cette même exécution JUnit dans votre pipeline. Le forfait gratuit (Free) d'Apidog permet d'accueillir jusqu'à 4 utilisateurs.

Pourquoi l'échéance du 11 novembre est cruciale

Le projet Node.js a annoncé une nouvelle série de correctifs pour les branches 26.x, 24.x et 22.x prévue le 11 novembre 2026 ou peu après, avec une sévérité maximale à nouveau classée HIGH. Aucun identifiant CVE n'est encore public. Notre guide sur les versions de novembre explique comment vous y préparer.

Corrigez la vulnérabilité Brotli dès aujourd'hui au lieu d'attendre cette prochaine fenêtre de tir. Les détails techniques de la faille sont désormais publics et des attaques réelles ont lieu en ce moment même. De plus, la mise à niveau menée cette semaine servira de répétition générale pour la suivante : même inventaire, même reconstruction d'images, même suite de tests. Les affaires PHP2Shell et React2Shell ont suivi la même trajectoire.

FAQ

La faille CVE-2026-111497 fait-elle l'objet d'exploitations actives ? Oui. La CISA l'a inscrite à son catalogue KEV (Known Exploited Vulnerabilities) le 27 octobre 2026 sous le libellé Google Brotli, et ELLIO a observé du trafic d'exploitation dès le 26 octobre.

Sa sévérité est-elle Élevée (HIGH) ou Critique (CRITICAL) ? Les deux qualifications sont légitimes. Node.js la classe comme HIGH. Le NVD lui attribue un score CVSS 3.1 de 9.8 CRITICAL, et le score CVSS 4.0 publié par Google atteint 9.2. Organisez-vous en partant du principe qu'elle est activement exploitée.

J'utilise Express 4. Suis-je à l'abri ? Vos corps de requête n'atteignent pas le décodeur, mais les appels à fetch(), axios et node:zlib restent vulnérables. Par ailleurs, cette même version corrige neuf autres CVE : mettez donc à niveau sans hésiter.

Node.js 20 est-il concerné ? L'équipe du projet n'évalue pas les branches en fin de vie (EOL) et ne publie aucun correctif pour celles-ci. Considérez les versions 20.x et 25.x comme non corrigées et non évaluées, et planifiez votre migration.

D'autres technologies que Node.js sont-elles touchées ? Oui. Le bulletin de sécurité GitHub mentionne les paquets PyPI brotli et brotlicffi, et des correctifs ont été signalés pour Bun 1.4.4 ainsi que pour .NET. Mettez à jour chaque décodeur séparément, car la mise à niveau de Node.js ne protège que sa propre bibliothèque intégrée.

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API