26 octobre 2026 7 min de lecture

CVE-2026-111497 : une faille dans le décodeur Brotli affecte Node.js, Bun, Python, .NET et Envoy — ce que vous devez mettre à jour maintenant

Une erreur dans le décodeur Brotli de Google (versions 1.0.3 à 1.2.0) permet, au moyen de données forgées, une écriture hors limites pouvant aller jusqu’à l’exécution de code (CVE-2026-111497, CVSS 9.2). Tout logiciel qui décompresse des données Brotli provenant de sources externes est concerné : Node.js, Bun, Python avec Brotli/brotlicffi, .NET, Envoy, curl. Des mises à jour sont disponibles.

Le décodeur Brotli de Google contient, dans les versions 1.0.3 à 1.2.0, une erreur qui permet à des données Brotli forgées d’écraser de la mémoire hors d’un tampon. La faille porte l’identifiant CVE-2026-111497 et une note de 9.2 selon CVSS 4.0 ; elle est connue publiquement sous les noms Node2Shell et Broccoli2Shell. Les conséquences possibles sont un plantage, la lecture de la mémoire du processus ou l’exécution de code. Imperva a démontré l’exécution de code sur un Node.js 24.22.0 non modifié. Du code de preuve de concept est en partie public, mais aucune attaque active n’est connue à ce jour. Node.js a publié les correctifs le 21 octobre 2026, les autres écosystèmes ont suivi jusqu’au 26 octobre.

Après cette annonce, j’ai vérifié mes propres systèmes : le runner de build de ce site utilisait encore Node.js 22.23.1, alors que la version 22.23.4 était disponible depuis plusieurs jours. La raison est expliquée dans la section consacrée à GitHub Actions plus bas ; elle concerne tous les runners auto-hébergés utilisant actions/setup-node.

Assistance pour l’inventaire et les mises à jour

Si vous avez besoin d’aide pour identifier les composants concernés dans des applications, des images de conteneur ou des pipelines CI, utilisez le formulaire de contact sur adeptio.ch. Je vous répondrai également à court terme.

Cause

L’erreur se situe dans la fonction DecodeBlockTypeAndLength(). Elle traite les changements de bloc dans le flux de données compressé, c’est-à-dire les emplacements où le décodeur passe à un autre code Huffman. Dans les versions vulnérables, la fonction ne renvoie qu’une valeur booléenne ; BROTLI_FALSE signifie à la fois « flux de données incorrect » et « entrée supplémentaire nécessaire ». Un flux forgé déclare un seul type de bloc et épuise sa longueur, forçant ainsi un changement qui ne peut pas réussir. Le décodeur interprète cela comme une entrée manquante, ajoute des octets supplémentaires à un tampon interne de 8 octets et écrit ainsi au-delà de sa fin.

Le correctif upstream (commit 0ed4268 dans le dépôt google/brotli) introduit un code d’erreur distinct BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH et interrompt le décodage. OpenAI Codex Security avait déjà signalé l’erreur en février 2026. Le correctif avait alors été intégré au code source, mais n’avait pas été considéré comme une correction de sécurité et n’était apparu dans aucune version. Il n’a été livré qu’avec Brotli 1.2.1 et les versions de Node.js du 21 octobre 2026.

Quand un système est vulnérable

Compresser avec Brotli ne présente aucun risque ; seuls sont vulnérables ceux qui décompressent des données Brotli provenant d’une source externe. Il existe deux directions :

  • Client : l’application récupère une URL et décode une réponse avec Content-Encoding: br. Le fetch() intégré de Node.js et Bun le fait automatiquement et ne peut pas être désactivé. Sont donc concernés les crawlers, les récepteurs de webhooks avec rappel, les aperçus de liens, les scripts de surveillance et toute automatisation qui charge du contenu depuis des serveurs tiers. Pour cela, il suffit à un attaquant de contrôler l’un des serveurs interrogés.
  • Serveur : un framework ou un middleware décompresse des corps de requête avec Content-Encoding: br. Imperva cite pour Node.js body-parser 2.0.0 à 2.3.0 et Express 5.0.0 à 5.3.0 avec des parseurs configurés json() ou raw(). Un serveur http Node.js nu ne décode pas lui-même les corps entrants.

Apache mod_brotli et les modules Brotli répandus pour nginx ne font que compresser et ne sont donc pas concernés. Envoy et Istio ne sont vulnérables que si le filtre de décompression Brotli est configuré ; Istio ne l’active pas par défaut.

Composants concernés et versions corrigées

ComposantVersions corrigéesRemarque
libbrotli (Google Brotli)1.2.1, 1.1.1, 1.0.10les versions 1.0.3 à 1.2.0 sont concernées
Node.js26.12.1, 24.22.1, 22.23.4version du 21.10.2026, contient d’autres correctifs (DNS, vérification des noms TLS)
Bun1.4.4reconstruire les exécutables créés avec bun build --compile
Python Brotli1.2.1utilisé automatiquement par urllib3, requests et aiohttp lorsqu’il est installé
Python brotlicffi1.2.1.0idem ; également comme extra httpx[brotli]
.NET8.0.33, 9.0.22, 10.0.14, 11 RC3mise à jour hors bande du 25.10.2026 ; .NET Framework n’est pas concerné, .NET 7 n’a pas de correctif
Envoy1.40.0, 1.39.3, 1.38.6, 1.37.8uniquement avec le filtre de décompression Brotli
Istio1.31.2, 1.30.6, 1.29.9uniquement avec un décompresseur Brotli dans un EnvoyFilter
Java brotli4j1.24.0le wrapper JNI embarque sa propre copie de Brotli
curl/libcurlcompilation avec Brotli 1.2.1uniquement avec --compressed ou CURLOPT_ACCEPT_ENCODING

Les autres bindings pour PHP, Ruby et Go (cgo) dépendent de la libbrotli du système ou embarquée. Parmi les distributions Linux, Debian 12 et 13, Alpine et Amazon Linux 2023 disposaient de paquets corrigés le 26 octobre ; Fedora et Red Hat étaient partiellement corrigés, tandis que le correctif était encore en attente pour Ubuntu et SUSE.

Trouver les versions concernées

Pour Node.js, Python et la bibliothèque système, trois commandes suffisent. Sous Windows, node -v donne le même résultat que sous Linux.

node -v
pip show Brotli brotlicffi
pipdeptree -r -p Brotli
Explication des options
OptionEffet
node -vaffiche la version de l’installation Node.js active
pip show Brotli brotlicffiaffiche la version et les dépendants des deux paquets Python, s’ils sont installés
pipdeptreerépertorie l’arbre de dépendances des paquets Python installés (à installer séparément)
-rinverse l’arbre : affiche quels paquets incluent le paquet indiqué
-p Brotlilimite la sortie au paquet Brotli

Sous Debian/Ubuntu et Alpine, le gestionnaire de paquets affiche la version de la bibliothèque système :

dpkg -l 'libbrotli*'
apk info -v brotli-libs
Explication des options
OptionEffet
dpkg -l 'libbrotli*'liste tous les paquets installés dont le nom commence par libbrotli, avec leur version
apk info -v brotli-libsaffiche le paquet Alpine brotli-libs avec son numéro de version

Les images de conteneur doivent être vérifiées séparément : un hôte mis à jour ne sert à rien si l’image contient une ancienne version de Node.js ou une libbrotli embarquée. Après la mise à jour, les images doivent être reconstruites et les workloads en cours redémarrés ; pour Bun et brotli4j, cela s’applique également aux applications qui lient Brotli statiquement.

Runners GitHub auto-hébergés : setup-node prend la version depuis le cache

actions/setup-node avec node-version: 22 ne vérifie pas par défaut si une version 22 plus récente existe. Si une version appropriée est déjà présente dans le cache d’outils du runner, elle est utilisée. Sur les runners hébergés par GitHub, l’image est régulièrement redéployée ; un runner auto-hébergé conserve en revanche son cache jusqu’à ce que quelqu’un le vide. Le journal indique alors par exemple Found in cache @ .../_tool/node/22.23.1/x64.

Une ligne supplémentaire dans chaque étape setup-node résout le problème :

- uses: actions/setup-node@v4
  with:
    node-version: 22
    check-latest: true
Explication des options
OptionEffet
node-version: 22sélectionne la version disponible la plus récente de la branche 22.x
check-latest: trueinterroge le répertoire des versions de Node.js à chaque exécution et télécharge une version plus récente au lieu d’utiliser celle du cache d’outils

Il est également possible d’indiquer explicitement la version minimale (node-version: 22.23.4) ; elle doit alors être mise à jour à chaque publication de sécurité. C’est particulièrement pertinent pour les pipelines qui récupèrent du contenu depuis des serveurs externes, tels que les scanners, les vérificateurs de liens ou les flux : fetch() y communique avec des serveurs que vous ne contrôlez pas, et le runner a généralement accès aux secrets de déploiement.

Si une mise à jour immédiate n’est pas possible

Les mesures d’atténuation agissent au niveau du décodage :

  • Entrant : rejeter au niveau du proxy inverse ou du middleware les requêtes dont Content-Encoding contient br. La comparaison doit ignorer la casse et couvrir également les listes telles que gzip, br.
  • Sortant : retirer br de Accept-Encoding et rejeter les réponses avec Content-Encoding: br avant le décodage. Le retirer uniquement de Accept-Encoding ne suffit pas, car un serveur forgé peut tout de même envoyer cet encodage. Cela n’est pas possible avec le fetch() intégré de Node.js et Bun ; seule la mise à jour aide dans ce cas.
  • curl : omettre --compressed ; dans libcurl, laisser CURLOPT_ACCEPT_ENCODING sur NULL.
  • Python : désinstaller Brotli et brotlicffi, et supprimer des dépendances les extras tels que httpx[brotli]. urllib3, requests et aiohttp reviennent alors à gzip et deflate.
  • Envoy/Istio : supprimer le décompresseur Brotli de la configuration ou des EnvoyFilters et vérifier la configuration en cours d’exécution.

Cloudflare Workers et navigateurs

Les personnes qui exploitent des applications sous forme de Cloudflare Worker n’exécutent pas leur propre processus Node.js ; le runtime workerd est exploité et mis à jour par Cloudflare. Cloudflare n’avait pas publié de déclaration sur CVE-2026-111497 au 26 octobre ; les clients ne peuvent rien modifier dans le runtime lui-même. Les outils autour du Worker restent toutefois concernés : les scripts de build, wrangler et les environnements de développement locaux s’exécutent sur Node.js et devraient utiliser une version corrigée. Les navigateurs utilisent leurs propres implémentations de Brotli ; ils ne sont pas cités comme concernés dans les communications des éditeurs et des chercheurs en sécurité.

Chronologie

DateÉvénement
Février 2026OpenAI Codex Security signale l’erreur, le correctif arrive dans le code source de Brotli sans publication
21.10.2026Node.js publie 26.12.1, 24.22.1 et 22.23.4
22.10.2026Brotli 1.2.1 et brotlicffi 1.2.1.0 sur PyPI ; analyse d’Imperva avec exécution de code
23.10.2026Correctifs pour libbrotli, Bun, Envoy et Istio
24.10.2026brotli4j 1.24.0, paquets pour Amazon Linux 2023
25.10.2026Mises à jour hors bande pour .NET
26.10.2026Debian et Alpine corrigés, Fedora et Red Hat partiellement

Sources

  1. Node.js: October 2026 Security Releases

    avis officiel avec la cause, les branches concernées et les versions corrigées, ainsi que neuf autres CVE de la même publication.

    https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
  2. NVD: CVE-2026-111497

    entrée CVE avec une note CVSS 4.0 de 9.2.

    https://nvd.nist.gov/vuln/detail/cve-2026-111497
  3. Imperva: Node2Shell, from Brotli data to remote code execution

    analyse technique démontrant l’exécution de code, les chemins client et serveur dans Node.js, ainsi que les versions concernées d’Express et body-parser.

    https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/
  4. Aikido: Python packages vulnerable to Node2Shell

    cause dans DecodeBlockTypeAndLength(), versions corrigées dans tous les écosystèmes, chronologie et mesures d’atténuation ; mise à jour en continu.

    https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497
  5. Microsoft .NET Blog: .NET October 2026 out-of-band security updates

    versions hors bande pour les versions .NET prises en charge.

    https://devblogs.microsoft.com/dotnet/dotnet-october-2026-oob-security-updates/
  6. Broccoli2Shell

    page d’information sur la faille sous son second nom.

    https://broccoli2shell.com/
  7. heise online: Faille du décodeur Brotli non seulement dans Node.js, mais aussi dans Bun, Python et plus encore
  8. actions/setup-node: check-latest

    documentation de l’option qui vérifie le cache d’outils par rapport au répertoire des versions à chaque exécution.

    https://github.com/actions/setup-node#check-latest-version

Commentaires

Les commentaires sont chargés depuis GitHub / Giscus.