Vulnérabilité RCE de React (CVE-2025-55182) – Problème et causes

La vulnérabilité des React Server Components (CVE-2025-55182, communément appelée React2Shell / React4Shell) révélée début décembre 2025 est un problème CVSS 10.0 qui permet l’exécution de code à distance (RCE) sans authentification préalable. Un PoC public et des tentatives de scan/attaque réelles ont déjà été observés.

Cet article propose une version plus structurée de « qui, pourquoi, jusqu’où est‑il dangereux ».


Résumé en un coup d’œil



  • Cœur du problème La faille réside dans la logique de désérialisation du protocole Flight utilisée par React Server Components (RSC). Un attaquant peut envoyer une requête manipulée qui entraîne l’exécution de code JavaScript arbitraire sur le serveur.

  • Composants principaux affectés

  • react-server-dom-webpack / -parcel / -turbopack 19.0 / 19.1.0 / 19.1.1 / 19.2.0
  • Les versions de Next.js 15.x, 16.x, 14.3.0‑canary.77 et ultérieures (lorsqu’on utilise le App Router)

  • Applications React SPA classiques Les applications React purement côté client qui n’utilisent pas RSC, Server Actions ou rendu côté serveur ne sont pas touchées.

  • Ce qu’il faut faire immédiatement si vous avez déjà utilisé Next.js 1. Vérifiez les versions de react-server-dom-* et next dans votre projet. 2. Mettez React à 19.0.1 / 19.1.2 / 19.2.1 ou plus récent. 3. Mettez Next.js à la version patchée (15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7, etc.) ou rétrogradez vers une version stable. 4. Si votre serveur est exposé sur Internet, vérifiez les logs, les règles WAF et les signes d’anomalies.


image

Qu’est‑ce qui a été découvert

En résumé, la vulnérabilité concerne :

  • Cible : implémentation RSC (react-server-dom-*).
  • Zone vulnérable : logique de décodage (désérialisation) du protocole Flight lorsqu’on transmet des données RSC du client vers le serveur.
  • Méthode d’attaque :
  • L’attaquant envoie un payload Flight spécialement manipulé à l’endpoint HTTP RSC/Server Actions.
  • Le serveur « fait confiance » à ces données et, lors de la désérialisation, le chargement de modules ou la création d’objets est détourné.
  • Résultat : exécution de code arbitraire sur le serveur.

L’élément clé est que l’attaque est non authentifiée. Toute instance Next.js RSC exposée sur Internet devient un objectif dès qu’elle est accessible.


Conditions précises de l’exploitation



1. Versions React/Next.js

Package Versions vulnérables Versions patchées
react-server-dom-webpack 19.0, 19.1.0, 19.1.1, 19.2.0 19.0.1, 19.1.2, 19.2.1
react-server-dom-parcel 19.0, 19.1.0, 19.1.1, 19.2.0 19.0.1, 19.1.2, 19.2.1
react-server-dom-turbopack 19.0, 19.1.0, 19.1.1, 19.2.0 19.0.1, 19.1.2, 19.2.1
Next.js (App Router) 14.3.0‑canary.77 +  15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7

2. Architecture / Runtime

L’exploitation est probable uniquement si tous les critères suivants sont réunis : 1. Utilisation de RSC (Next.js App Router ou autre framework compatible). 2. Exécution de code React côté serveur (Node.js, etc.). 3. Serveur exposé via HTTP (Internet ou intranet).

En revanche, les environnements suivants sont pratiquement immunisés : * SPA React purement client (CRA/Vite). * Déploiement de bundles statiques sur S3, CDN, etc. * Architecture où React tourne uniquement dans le navigateur et le serveur est une API distincte (ex : React + Django REST, React + FastAPI).


Pourquoi les combinaisons React‑DRF ou React‑FastAPI restent sûres

Dans une architecture où React est couplé à un backend Python (Django REST Framework ou FastAPI), le problème n’apparaît pas : 1. React ne s’exécute pas côté serveur ; il reste dans le navigateur. 2. La frontière de communication est claire : React ↔ API via JSON/HTTP. 3. Le serveur ne comprend pas le protocole Flight et ne charge pas de modules React côté serveur. 4. RSC, Server Actions et Flight ne sont pas utilisés.

En résumé, la faille cible uniquement les environnements où le protocole Flight est désérialisé côté serveur, ce qui n’est pas le cas dans les architectures React‑SPA + REST.


Protocole Flight et contamination de prototype côté serveur

Techniquement, la vulnérabilité suit le schéma classique : désérialisation Flight → contamination de prototype → RCE.

1. Modèle de code problématique

// Version vulnérable (conceptuelle)
export function requireModule<T>(metadata: ClientReference<T>): T {
  const moduleExports = parcelRequire(metadata[ID]); // chargement du module
  return moduleExports[metadata[NAME]];              // utilisation directe de l’entrée client
}
  • metadata[ID] : identifiant du module à charger.
  • metadata[NAME] : nom de l’export à récupérer.

Le problème est que metadata[NAME] est utilisé sans validation. Un attaquant peut fournir __proto__ ou constructor, ouvrant la porte à la contamination du prototype.

2. Contamination → RCE

Si un objet est créé à partir d’un prototype contaminé, les propriétés indésirables (ex : spawnSync('sh')) peuvent être héritées. Ainsi, un simple appel HTTP peut déclencher l’exécution de code sur le serveur.


Ce qui a été corrigé

La correction principale consiste à ne plus faire confiance aux valeurs envoyées par le client. Le patch modifie requireModule :

// Version corrigée (conceptuelle)
export function requireModule<T>(metadata: ClientReference<T>): T {
  const moduleExports = parcelRequire(metadata[ID]);
  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
    return moduleExports[metadata[NAME]];
  }
  return undefined as any;
}

Cette simple vérification empêche l’accès aux propriétés non propres, bloquant ainsi la contamination du prototype.

Le patch inclut également : * Renforcement de la validation de la structure du payload Flight. * Restrictions sur certains champs sensibles. * Logique de défense supplémentaire dans les chemins de code concernés.


Conflit structurel introduit par l’expansion de React vers le serveur

React a été conçu comme une bibliothèque UI côté client. Avec RSC et Server Actions, il a été étendu pour fonctionner côté serveur. Next.js a intégré ces fonctionnalités, créant un app hybride où les composants client, serveur et actions coexistent.

Cette intégration a introduit un modèle de confiance front‑end dans un contexte serveur, ce qui a créé la faille. Les principes suivants étaient mal adaptés : * Modules chargés dynamiquement à partir de données non fiables. * Pas de schéma strict pour le payload Flight. * Pas de signature ou d’intégrité des requêtes.

Une nouvelle approche de sécurité aurait dû inclure : * Validation stricte du schéma Flight. * Liste blanche des valeurs contrôlables par le client. * Signatures HMAC ou mécanismes d’intégrité.


Conclusion : redéfinir le modèle de sécurité quand front‑end et back‑end se confondent

Cette vulnérabilité montre que lorsqu’une bibliothèque front‑end est étendue pour s’exécuter côté serveur, le modèle de confiance doit être repensé. Les architectures traditionnelles React + DRF/FastAPI restent sûres car le code React ne s’exécute pas côté serveur.

Les frameworks qui fusionnent front‑end et back‑end (Next.js, etc.) doivent concevoir des modèles de sécurité et des mécanismes de validation dès le départ. La facilité d’utilisation ne doit pas primer sur la sécurité.

Les frameworks qui effacent la frontière front‑back‑end continueront d’émerger ; il est crucial de mettre la sécurité au premier plan dès la conception.