Les leçons de l’incident React RCE : pourquoi la signature HMAC, la rotation des clés et le Zero Trust sont indispensables

Ce que la faille RCE a révélé : « Une fois que vous faites confiance aux données, vous avez perdu »



La faille RCE (CVE-2025-55182) survenue dans React Server Components/Next.js ne se résume pas à « React a été compromis ». Le message central est bien plus fondamental.

« Si vous faites confiance à des données envoyées par le client, vous finirez inévitablement compromis »

La nature de cette faille est que le serveur utilisait les données Flight protocol (métadonnées) envoyées par le client sans vérification suffisante pour charger des modules et accéder à des objets.

  • « Cette valeur sera sécurisée par React »
  • « Ce n’est pas notre API, donc c’est sûr »

Cette confiance implicite s’est accumulée jusqu’à un point où une RCE était possible sans authentification préalable.

Il faut donc changer la question.

  • « Pourquoi React a été compromis »
  • « Sur quelles données faisons-nous confiance sans signature ni vérification ? »

La réponse à cette question introduit naturellement les concepts de signature HMAC et de Zero Trust.


Pourquoi la signature HMAC est cruciale : « Ces données proviennent réellement de notre serveur ? »

Les systèmes réels dépendent beaucoup de la confiance entre serveurs.

  • Front‑end ↔ Back‑end
  • Micro‑service A ↔ B
  • Back‑end ↔ Back‑end (tâches asynchrones, file d’attente, Webhook, API interne, etc.)

Les données échangées sont souvent supposées ainsi :

« Cette URL n’est pas exposée à l’extérieur, donc elle sera appelée uniquement par le système interne »

« Ce format de token est connu uniquement par notre service, donc c’est sûr »

Mais les attaquants cherchent toujours à briser ces hypothèses.

Dans ce contexte, HMAC (HMAC‑SHA256, par exemple) répond à une question fondamentale.

« Cette requête/message a-t‑il réellement été créé par quelqu’un qui connaît notre clé secrète ? »

En d’autres termes :

  • Seul celui qui connaît la clé HMAC peut générer une signature valide.
  • Le serveur reçoit payload + signature et peut vérifier :
  • « La signature est correcte »
  • « Il n’y a pas eu de modification en transit »

Un monde sans signature HMAC

Que se passe‑t‑il pour les REST/Webhook/​API internes sans signature ?

  • Si un attaquant connaît la structure de l’URL et les paramètres, il peut
  • Créer des requêtes arbitraires et faire croire au serveur qu’il s’agit d’une requête interne naturelle.

Par exemple :

POST /internal/run-action
Content-Type: application/json

{
  "action": "promoteUser",
  "userId": 123
}

Même si c’était un point de terminaison interne appelé uniquement depuis le back‑office, un filtrage réseau compromis, une faille de proxy interne, ou la publication accidentelle de code, de logs ou de documentation peuvent permettre à un attaquant de simuler un appel interne.

Si une signature HMAC était présente, la situation changerait radicalement.

  • Le corps complet de la requête serait signé.
  • Le serveur vérifierait la signature à chaque requête.

« Même si vous connaissez l’URL ou les paramètres, sans la clé vous ne pouvez pas créer de requête valide »


Exemple : protéger une action interne avec une signature HMAC



Voici un exemple simple (pseudo‑code TypeScript/Node.js).

1. Supposons que le serveur possède une clé secrète partagée

const HMAC_SECRET = process.env.HMAC_SECRET!; // injectée depuis .env ou Secret Manager

2. Le client (ou un service interne) crée la requête

import crypto from 'crypto';

function signPayload(payload: object): string {
  const json = JSON.stringify(payload);
  return crypto
    .createHmac('sha256', HMAC_SECRET)
    .update(json)
    .digest('hex');
}

const payload = {
  action: 'promoteUser',
  userId: 123,
};

const signature = signPayload(payload);

// Envoi
fetch('/internal/run-action', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Signature': signature,
  },
  body: JSON.stringify(payload),
});

3. Le serveur vérifie la signature

function verifySignature(payload: any, signature: string): boolean {
  const json = JSON.stringify(payload);
  const expected = crypto
    .createHmac('sha256', HMAC_SECRET)
    .update(json)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex'),
  );
}

app.post('/internal/run-action', (req, res) => {
  const signature = req.headers['x-signature'];

  if (!signature || !verifySignature(req.body, String(signature))) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Arrivé ici signifie :
  // 1) le payload n’a pas été modifié
  // 2) la requête provient d’un acteur connaissant HMAC_SECRET
  handleInternalAction(req.body);
});

Cette structure est le schéma de base pour prouver que ces données proviennent réellement de notre côté.


Si plusieurs administrateurs (opérateurs/développeurs) existent : la rotation des clés HMAC est « obligatoire, pas optionnelle »

Un autre problème réaliste avec les clés HMAC concerne les personnes.

  • Opérateurs, SRE, développeurs back‑end, prestataires externes, stagiaires…
  • Même si tout le monde n’a pas accès à .env, il y a toujours un risque d’exposition via GitOps, CI/CD, documentation, Slack, Notion, etc.

L’essentiel est de construire autour de l’hypothèse que « une clé peut être exposée ».

« On suppose qu’une clé peut être exposée »

En conséquence, la rotation des clés HMAC devient indispensable.

Pourquoi la rotation est nécessaire

  1. Les personnes changent * Départ, changement d’équipe, fin de contrat de sous‑traitant * L’ancien détenteur de la clé ne doit plus y avoir accès.
  2. On ne peut pas suivre toutes les expositions * DM Slack, notes locales, captures d’écran, etc. * Il est pratiquement impossible de garantir qu’une clé n’a jamais été exposée.
  3. Après un incident, on doit pouvoir réagir * Si une clé antérieure a été exposée, on peut déclarer que « tout ce qui a été signé avec cette clé est désormais invalide ».

Modèle de rotation en pratique

Dans une organisation avec plusieurs administrateurs, on recommande généralement :

  1. Gestion des versions de clé * HMAC_SECRET_V1, HMAC_SECRET_V2, etc. * Envoyer le kid (key id) dans l’en‑tête ou le payload.
  2. Le serveur conserve plusieurs clés et valide selon la version * Par exemple, accepter V1 et V2, puis après un délai, ne garder que V2.
  3. Documenter le processus de rotation * « Créer une nouvelle clé → déployer → basculer créateur/validateur → supprimer l’ancienne » * Mettre en place un checklist + runbook pour que même en cas de changement de personnel, le processus reste cohérent.
  4. Séparer les rôles * Personne qui crée/gestionne la clé vs personne qui modifie le code.

Une clé HMAC « une fois définie, fin » conduit à une rupture totale du système si elle est exposée. La rotation limite ce risque dans le temps.


Zero Trust : « La confiance n’est pas un état, c’est une construction à chaque requête »

Enfin, l’incident React RCE rappelle un principe de base de la sécurité.

« La sécurité repose sur le Zero Trust »

Le Zero Trust est simple :

  • « Parce qu’il est interne, c’est sûr »
  • « Parce qu’il est utilisé par le front, c’est sûr »
  • « Parce que c’est notre framework, c’est protégé »

Ces affirmations sont interdites. On doit plutôt se poser :

  • « Cette entrée a‑t‑elle été conçue en supposant un attaquant ? »
  • « Cette requête provient‑t‑elle réellement de l’entité prévue ? »
  • « Comment pouvons‑nous vérifier qu’elle n’a pas été modifiée ? »
  • « Si la clé est exposée, quel est l’impact et comment le récupérer ? »

Dans le cas de React RCE, les données Flight étaient traitées sous l’hypothèse « React les fournit », ce qui a conduit à une manipulation directe du chemin de chargement de modules serveur.

Du point de vue Zero Trust, cela aurait dû être vu comme un signal d’alerte immédiat.

Les premières défenses à envisager :

  • Signature HMAC (intégrité et provenance)
  • Rotation des clés (limiter l’impact d’une fuite)

Résumé : « Ne faites pas confiance, faites prouver »

Les trois messages clés de cet article sont :

  1. Ne faites pas confiance aux données par défaut * Même les données internes traversant le réseau peuvent devenir un vecteur d’attaque.
  2. La signature HMAC est l’outil de base pour vérifier l’origine * Appliquez‑la à toutes les API REST, Webhooks, RPC internes, messages asynchrones. * En environnement multi‑administrateurs, imposez la rotation des clés.
  3. Le Zero Trust est la base * La confiance ne doit pas être accordée automatiquement, elle doit être reconstituée à chaque requête.

L’incident React RCE rappelle que la frontière entre front‑end et back‑end s’estompe, et que la vigilance doit être constante.

« Ne faites pas confiance, vérifiez. Mettez la vérification dans le code, les processus et la politique de gestion des clés. »

La première étape est la signature HMAC et la rotation des clés, sur laquelle repose la philosophie du Zero Trust.

image