Retour
Vulnérabilités & CVE8 août 2026 · 6 min de lecture

React2Shell : comment une faille de désérialisation a mis React Server Components à 10/10

par detektd team

Vitre fissurée en étoile, en gros plan sur fond flou
Photo : rawpixel · CC0 · rawpixel

Le 3 décembre 2025, Meta a publié CVE-2025-55182, une faille dans React Server Components notée 10,0 sur 10 en CVSS, le maximum. Découverte et signalée par le chercheur Lachlan Davidson, elle permettait à un attaquant non authentifié d'exécuter du code arbitraire sur le serveur, avec une simple requête HTTP. Une preuve de concept publique est apparue dès le lendemain. Le 5 décembre, la CISA l'ajoutait à son catalogue des vulnérabilités activement exploitées (KEV). Le surnom est resté : React2Shell.

Huit mois plus tard, la faille reste un cas d'école, parce qu'elle touche le cœur de l'architecture moderne de React, et parce que la question qu'elle pose dépasse ce bug précis : que se passe-t-il quand un framework rend la frontière entre client et serveur presque invisible pour le développeur ?

Ce qu'est le protocole Flight

React Server Components (RSC) permet d'exécuter une partie de l'arbre de composants sur le serveur, puis d'envoyer le résultat au navigateur. Ce résultat n'est pas du HTML, mais un flux sérialisé dans un format propre à React, baptisé « Flight ». Il décrit l'arbre rendu, les références vers les composants client à charger, les promesses encore en cours de résolution, et les références vers d'autres morceaux du flux. C'est un format riche : il sait représenter des objets imbriqués, des références croisées entre morceaux, et des valeurs qui arrivent plus tard.

Le protocole fonctionne aussi dans l'autre sens. Les Server Functions (les fonctions marquées "use server", que Next.js appelle Server Actions) permettent au navigateur d'appeler une fonction du serveur comme s'il s'agissait d'une fonction locale. Côté réseau, c'est une requête POST vers la page, avec un en-tête qui identifie l'action et, dans le corps, les arguments encodés... au format Flight. Le serveur doit donc désérialiser un flux Flight fourni par le client. C'est exactement là que se trouvait la faille.

Requête POST vers une page RSC
Corps au format Flight, contrôlé par l'attaquant
Désérialisation avant toute logique applicative
Exécution de code sur le serveur

Le mécanisme de la faille

Les analyses publiées par Rapid7, Qualys, Unit 42 ou Akamai décrivent le même mécanisme, sans qu'il soit nécessaire d'entrer dans le détail d'une charge utile. Le désérialiseur Flight résout les références internes du flux : un morceau peut pointer vers un autre, ou vers une propriété d'un autre. Dans les versions vulnérables, cette résolution ne limitait pas suffisamment les chemins autorisés : un flux construit à la main pouvait remonter la chaîne de prototypes JavaScript des objets manipulés, jusqu'à atteindre le constructeur Function, l'équivalent d'un eval. À partir de là, le serveur exécutait du code fourni par la requête.

C'est une variante moderne d'une famille de failles bien connue : la désérialisation non sûre. Java avec ses gadgets de sérialisation, PHP avec unserialize(), Python avec pickle : à chaque fois, le problème est le même. Un format de sérialisation assez expressif pour reconstruire des objets complexes devient un langage, et si l'entrée vient d'un client, c'est le client qui écrit le programme.

Vulnérable par défaut

Le détail le plus important est aussi le plus contre-intuitif. L'avis de React le dit explicitement : une application pouvait être vulnérable même si elle ne déclarait aucune Server Function, du moment qu'elle utilisait React Server Components. Le point d'entrée de désérialisation existait dès que le framework savait traiter des actions. Autrement dit, un site Next.js en App Router, sans une seule ligne "use server", était exposé. Beaucoup d'équipes se sont crues à l'abri pour cette raison.

0,0

score CVSS de CVE-2025-55182, le maximum possible, exploitable sans authentification ni interaction

Qui était touché, exactement

La faille se trouve dans les paquets qui implémentent la partie serveur de RSC : react-server-dom-webpack, react-server-dom-parcel et react-server-dom-turbopack, en versions 19.0, 19.1.0, 19.1.1 et 19.2.0. Elle est corrigée en 19.0.1, 19.1.2 et 19.2.1. Tous les frameworks qui embarquent ces paquets héritent du problème : Next.js, React Router, Waku, RedwoodSDK, ainsi que les intégrations RSC de Parcel et Vite.

Pour Next.js, l'impact est suivi sous CVE-2025-66478. Sont concernées les applications App Router en Next.js 15.x et 16.x, ainsi que les canary 14.3.0-canary.77 et suivantes. Next.js 13.x, Next.js 14.x stable, les applications en Pages Router et le runtime Edge ne sont pas touchés. Les versions corrigées, une par branche :

Versions corrigées de Next.js (CVE-2025-66478)
15.0.x -> 15.0.5      15.3.x -> 15.3.6
15.1.x -> 15.1.9      15.4.x -> 15.4.8
15.2.x -> 15.2.6      15.5.x -> 15.5.7
16.0.x -> 16.0.7

canary: 15.6.0-canary.58 / 16.1.0-canary.12
14.3.0-canary.77+ : downgrade to the latest 14.x stable

Des heures, pas des jours

La fenêtre entre la publication et l'exploitation a été presque nulle. Les télémétries de plusieurs éditeurs montrent des scans automatisés dans les heures suivant l'annonce. Le Google Threat Intelligence Group a observé l'exploitation par de nombreux groupes, des cybercriminels opportunistes aux groupes soupçonnés d'espionnage, pour déployer des portes dérobées, des tunnels réseau et des mineurs de cryptomonnaie. AWS a documenté l'exploitation rapide par des groupes liés à la Chine, et Unit 42 des tentatives visant des conteneurs et des clusters Kubernetes chez les grands clouds.

Les fournisseurs d'hébergement et de CDN (Vercel, Netlify, Cloudflare, Fastly, Akamai) ont déployé des règles de filtrage pour bloquer les requêtes malveillantes connues. Mais Vercel a été clair : il n'existe aucun contournement, seule la mise à jour corrige. Une règle WAF bloque les variantes qu'elle connaît ; elle ne répare pas le désérialiseur.

Une semaine plus tard, deux failles de plus

Comme souvent après une faille majeure, l'attention s'est portée sur le même code. Le 11 décembre 2025, React a publié deux nouvelles vulnérabilités dans le même désérialiseur. CVE-2025-55184 (CVSS 7,5) permettait un déni de service : une structure auto-référente faisait tourner le serveur en boucle, processus vivant mais plus aucune réponse. CVE-2025-55183 (CVSS 5,3) permettait de faire renvoyer au serveur le code source d'une Server Function avec, le cas échéant, les secrets écrits en dur dedans. Un correctif incomplet du déni de service a ensuite donné lieu à CVE-2025-67779. Aucune ne permet d'exécuter du code, mais toutes exigent de passer à une version encore plus récente que le correctif initial.

Ce qu'il faut vérifier aujourd'hui

La première vérification prend dix secondes : regarder les versions réellement installées, y compris transitives. Un projet peut déclarer next@15 dans son package.json et tourner, via son lockfile, sur une version antérieure au correctif.

Versions installées de Next.js et du runtime RSC
npm ls next react react-dom --all
npm ls react-server-dom-webpack react-server-dom-turbopack --all

# Vercel's interactive checker / updater
npx fix-react2shell-next

La consigne que beaucoup ont ignorée

Next.js recommande de faire tourner tous les secrets de toute application restée en ligne sans correctif après le 4 décembre 2025 à 13 h (heure du Pacifique). Mettre à jour ferme la porte ; ça n'invalide pas les clés qu'un attaquant a pu lire pendant qu'elle était ouverte.

  • Mettre à jour vers la dernière version de sa branche, pas seulement vers le premier correctif : les CVE du 11 décembre exigent une version postérieure.
  • Ne jamais écrire de secret en dur dans une Server Function : CVE-2025-55183 a montré que leur code source peut sortir.
  • Surveiller les processus lancés par le serveur Node.js : un serveur web qui démarre un shell ou un binaire inconnu est le signal le plus fiable d'une exploitation.
  • Limiter les sorties réseau du conteneur applicatif : une porte dérobée qui ne peut pas contacter son serveur de commande est beaucoup moins utile.

Pour les apps détectées comme Next.js, detektd inclut une vérification dédiée à React2Shell. Elle cherche à établir si l'app expose le point d'entrée vulnérable sur une version non corrigée, sans jamais envoyer de charge capable d'exécuter quoi que ce soit, y compris sur les routes découvertes pendant l'exploration, pas seulement la page d'accueil, puisque sur de nombreux déploiements la racine est une page statique.

React2Shell : comment une faille de désérialisation a mis React Server Components à 10/10 | detektd