Node.js corrige 16 CVE : plantages HTTP/2 et un bug HTTPS qui laisse fuiter des clés TLS

Node.js corrige 16 CVE : plantages HTTP/2 et un bug HTTPS qui laisse fuiter des clés TLS

Le 11 novembre, le projet Node.js a publié des versions de sécurité pour ses trois lignes supportées : 22.23.5 (Jod), 24.22.3 (Krypton) et 26.13.1 (Lithium). Le lot couvre 16 CVE. Sept sont classées High, six Medium et trois Low, et les dépendances intégrées llhttp, undici et sqlite ont été mises à jour au passage.

Les problèmes sérieux se trouvent dans le code serveur propre à Node pour HTTP/2, HTTPS et TLS. Un bug permet à un client sans identifiants de tuer un serveur HTTP/2 par défaut. Un autre permet à un client de lire de la mémoire appartenant à d'autres connexions, y compris des clés privées TLS. Le projet ne signale aucune attaque connue, et la CISA n'en a ajouté aucune à sa liste KEV. L'avis ne mentionne par ailleurs aucun contournement. Soit vous mettez à jour, soit vous restez exposé.

Les bugs que nous lirions en premier

CVE-2026-123863 (CVSS 8,2, High) est une assertion atteignable dans la fermeture d'une session HTTP/2. Son déclencheur est assez banal : un serveur http2 standard dont le handler envoie une réponse avant que le client n'ait fini d'envoyer le corps de la requête. Un client distant peut ainsi faire tomber tout le processus, que ce soit en TLS ou en clair. C'est une variante de la CVE-2024-27983 qui a échappé au correctif précédent. Versions concernées : 24.x à partir de 24.22.0, et 26.x à partir de 26.9.0.

CVE-2026-123864 est celle qui m'a fait poser mon café. C'est un bug de réentrance dans la couche HTTPS de Node, qu'un attaquant sans authentification peut exploiter pour lire les données des connexions d'autres personnes. Cela peut être leurs requêtes, ou la clé privée TLS de votre serveur. Elle touche les versions 22.x, 24.x et 26.x. L'attaquant a besoin d'un handler d'une forme particulière : res.flushHeaders() appelé avant la fin du corps de la requête, puis res.end() avec un chunk non vide plus tard. De plus, une route doit renvoyer ou stocker un corps de requête, car c'est ainsi que les octets divulgués reviennent à l'attaquant. Du node:http simple, sans TLS, n'est pas concerné.

CVE-2026-123866 est un use-after-free dans la fermeture d'un flux HTTP/2. Il peut envoyer de la mémoire libérée, ou les données de réponse d'une autre connexion, au pair. Les trois lignes sont touchées.

CVE-2026-123872 est plus discrète mais vilaine si vous faites du mTLS. Lors d'une renégociation TLS 1.2, un client peut changer le servername et reporter une authentification par certificat client existante vers un hôte dont les règles de certificat client sont plus strictes. Si un même processus Node sert plusieurs noms d'hôte avec des exigences de certificat différentes, lisez celle-ci deux fois.

Vient ensuite la CVE-2026-126051, un plantage de serveur TLS déclenchable à distance. Elle touche les serveurs 24.x et 26.x qui utilisent SNICallback, OCSPRequest, newSession, resumeSession ou server.addContext().

Les lignes en fin de vie n'ont droit à rien. Si vous utilisez encore la 20.x ou la 25.x, cette version ne corrige rien pour vous.

Qui a trouvé tout cela ? Chris Rohlf, en collaboration avec Claude et Anthropic Research, a signalé les failles 123863, 123864 et plusieurs autres de cette version, et Matteo Collina a écrit la plupart des correctifs. À mon avis, la chasse aux bugs assistée par IA nous vaudra davantage de gros lots multi-CVE, pas moins. Adaptez votre processus de correctifs en conséquence.

Qui est réellement exposé

Le groupe à risque, ce sont les équipes qui terminent HTTP/2 ou HTTPS dans Node lui-même. C'est un groupe plus restreint que « tous ceux qui font tourner Node », mais plus large que ce que la plupart imaginent.

Quand nous construisons des applications cloud-native pour des clients grands comptes, Node se trouve généralement derrière un load balancer ou un reverse proxy qui gère le TLS et parle en HTTP/1.1 simple à l'application. Dans ce cas, le bug de fuite de clés ne vous atteint pas, car node:http en clair est hors périmètre. Mais dans notre travail sur Docker, nous croisons aussi l'autre type de service : une API d'administration, un récepteur de webhooks, un petit outil interne où quelqu'un a appelé directement https.createServer ou http2.createSecureServer parce que c'était plus rapide que de configurer un proxy. Personne ne se souvient de ces services au moment des mises à jour.

Notez aussi que la 123863 fonctionne en HTTP/2 en clair. Si vos services communiquent en h2c à l'intérieur d'un cluster, le fait que le TLS soit géré en amont ne vous protégera pas du plantage.

Les équipes mobiles doivent aussi y prêter attention. Dans nos projets natifs iOS et Android, le backend est souvent une API Node, et nous avons vu des équipes activer HTTP/2 directement dans Node pour le trafic des applications afin de réduire la latence. Si ce processus peut être planté à distance, vos utilisateurs voient des spinners et des requêtes en échec, alors que votre crash reporting n'indique rien d'anormal côté appareil. C'est un incident déroutant à déboguer à 2 h du matin.

Côté sécurité, les bugs de divulgation de mémoire m'inquiètent davantage que les plantages. Un plantage apparaît dans votre monitoring en quelques minutes. Une fuite ne réveille personne. Lors de nos missions de pentest pour des studios de jeux, les pires constats étaient rarement les plus bruyants. C'étaient les lectures silencieuses pour lesquelles personne n'avait de ligne de log. Et d'après notre travail anti-DDoS avec des clients de plateformes de voyage : quand nous configurons Cloudflare ou Akamai devant une origine, la première chose que nous testons est si l'origine reste joignable directement. Souvent, c'est le cas. Votre configuration en périphérie ne servira à rien si un attaquant peut parler au processus Node sans passer par elle.

Que faire dès aujourd'hui

  1. Faites l'inventaire de chaque processus Node, pas seulement de l'application principale. Lancez node -v dans chaque image de conteneur que vous déployez, y compris les cron jobs et les sidecars. Un tag d'image de base épinglé ne se mettra pas à jour tout seul : reconstruisez et redéployez.
  2. Passez à la 22.23.5, 24.22.3 ou 26.13.1, selon votre ligne. Aucun flag de configuration ne fait disparaître le problème.
  3. Cherchez dans votre code le motif de la fuite HTTPS : grep -rn "flushHeaders" . Si vous obtenez des résultats dans un handler HTTPS et qu'une route renvoie ou stocke des corps de requête, placez ce service en tête de file. S'il était exposé à Internet, renouveler sa clé TLS vous coûte peu, même sans attaque signalée.
  4. Si vous êtes en 20.x ou 25.x, inscrivez la migration au tableau de ce sprint. La repousser au trimestre prochain n'est plus une option.
  5. Vérifiez que vos origines n'acceptent que le trafic provenant de votre CDN ou de votre load balancer.

Rien de tout cela n'est glamour, et franchement, la mise à jour elle-même est souvent la partie facile. Retrouver le service oublié qui termine son propre TLS prend plus de temps. Pour avoir une idée de notre façon d'aborder ce type d'audit, notre présentation des services et nos réalisations vous donneront un aperçu, et notre équipe de développement s'occupe très régulièrement de ces mises à jour de runtime.

Si un service Node avec sa propre configuration TLS, que personne n'a touché depuis son lancement, vous rappelle quelque chose, parlons-en.

http2nodejstech-newstlsvulnerability