CVE-2025-29927 – Vulnérabilité de contournement d’autorisation dans Next.js : Tout ce que vous devez savoir

CVE-2025-29927 – CVE-2025-29927 -

Le 21 mars 2025, les mainteneurs de Next.js ont annoncé une nouvelle vulnérabilité permettant de contourner les mécanismes d’autorisation : CVE-2025-29927. Cette vulnérabilité peut être facilement exploitée afin de contourner les mécanismes d’autorisation. Dans certains cas, son exploitation peut également entraîner un empoisonnement du cache et un déni de service.

Quelles versions de Next.js sont concernées ?

Next.js 15.x – à partir de la version 15.0.0 jusqu’à la version 15.2.2 incluse.

Next.js 14.x – à partir de la version 14.0.0 jusqu’à la version 14.2.24 incluse.

Versions antérieures de Next.js – à partir de la version 11.1.4 jusqu’à la version 13.5.6 incluse.

Scénarios d’attaque pour la CVE-2025-29927

Pour que cette vulnérabilité puisse être exploitée, le serveur Next.js ciblé doit utiliser un middleware Next.js. Cela implique la présence d’un fichier middleware.js ou middleware.ts (_middleware.js ou _middleware.ts  pour les anciennes versions de Next.js). Ce fichier définit et exporte la fonction de middleware contenant la logique exécutée à la réception de chaque requête HTTP.

Contournement des mécanismes d’autorisation

Il s’agit du scénario d’exploitation le plus probable pour CVE-2025-29927.

Ce scénario concerne les serveurs Next.js ciblés qui utilisent la fonctionnalité de middleware pour effectuer les contrôles d’autorisation (et dont l’application sous-jacente n’utilise aucune autre couche d’autorisation).

Scénario avec un middleware d’autorisation sans exploitation de la CVE-2025-29927

Scénario avec un middleware d’autorisation et exploitation de la CVE-2025-29927

Déni de service par empoisonnement du cache

Le middleware Next.js peut également faciliter la localisation des sites web. Il peut, par exemple, rediriger automatiquement les utilisateurs en fonction de leur emplacement, en ajoutant /en pour les anglophones ou /fr pour les visiteurs francophones. Si une personne exploite la CVE-2025-29927 et contourne le middleware chargé de ces redirections, elle n’accédera pas à une page localisée, mais à la racine du site web (/), pour laquelle les développeurs n’ont jamais créé de page. Le résultat ? Une erreur 404 ou une erreur serveur 500, selon la configuration.

Si le site utilise un CDN ou une autre couche de mise en cache, ces réponses d’erreur peuvent être enregistrées dans le cache et présentées aux visiteurs suivants. Une fois ces réponses mises en cache, les utilisateurs légitimes risquent de voir des pages défectueuses partout dans le monde. Cela provoque une panne auto-infligée qui compromet gravement la disponibilité du service, sans qu’une seule ligne de code ait été modifiée.

Scénario avec un middleware de redirection sans exploitation de la CVE-2025-29927

Scénario avec un middleware de redirection et exploitation de la CVE-2025-29927

Comprendre le middleware Next.js

Le middleware Next.js est une fonctionnalité puissante, introduite dans Next.js v12, qui permet aux développeurs d’exécuter du code avant qu’une requête ne soit finalisée. Exécuté à la périphérie du réseau, plus près de l’utilisateur que le code traditionnel côté serveur, le middleware peut modifier les en-têtes de réponse, réécrire ou rediriger les requêtes et, surtout, mettre en œuvre des contrôles d’authentification et d’autorisation.

Dans Next.js, le middleware s’exécute avant le rendu et peut être configuré de manière à s’activer sur des chemins spécifiques grâce aux paramètres matcher.

Voici quelques exemples d’utilisation du middleware Next.js :

  • Vérification des jetons d’authentification
  • Mise en place d’un contrôle d’accès basé sur les rôles
  • Redirection des utilisateurs non authentifiés

Une implémentation typique de middleware Next.js qui effectue l’authentification pourrait ressembler à ceci :

 

 import { NextResponse } from 'next/server'
 import type { NextRequest } from 'next/server'

 export function middleware(request: NextRequest) {
   // Récupérer le jeton de l’utilisateur dans les cookies
   const token = request.cookies.get('token').value
  
   // Vérifier que l’utilisateur est authentifié
   const isAuthenticated = validateToken(token)
  
   // Si l’utilisateur n’est pas authentifié, le rediriger vers la page de connexion
   if (!isAuthenticated) {
     return NextResponse.redirect(new URL('/login', request.url))
   }
  
   // Poursuivre vers la route protégée si l’utilisateur est authentifié
   return NextResponse.next()
 }

 // Configurer les routes qui utilisent ce middleware
 export const config = {
   matcher: ['/dashboard/:path*', '/settings/:path*'],
 }
 

Analyse technique de la CVE-2025-29927

La CVE-2025-29927 révèle une faille critique dans la façon dont le middleware Next.js traite certains types de requêtes. Cette faille peut permettre de contourner les mécanismes d’authentification et d’autorisation.

Cette vulnérabilité affecte les applications qui, dans certaines configurations, utilisent un middleware pour contrôler les accès.

Elle provient du traitement incohérent, par Next.js, des en-têtes personnalisés x-middleware-subrequest. Lorsque cet en-tête est inclus dans les requêtes adressées à des routes protégées, Next.js autorise à tort la requête à contourner entièrement l’exécution du middleware. Cet en-tête force l’environnement d’exécution de Next.js à ignorer la phase d’évaluation du middleware, tout en continuant à traiter le gestionnaire de la route sous-jacente.

Pour exploiter cette vulnérabilité, il suffit à un pirate d’ajouter l’en-tête x-middleware-subrequest à ses requêtes HTTP lorsqu’il tente d’accéder à des ressources protégées. Par exemple, une requête adressée à /api/admin/users, normalement bloquée par les contrôles d’autorisation du middleware, sera traitée normalement si cet en-tête est présent. Le serveur traite la requête comme si le middleware l’avait déjà examinée et approuvée, ce qui entraîne un contournement complet des mécanismes de sécurité. Cette manipulation de l’en-tête peut être facilement réalisée à l’aide des outils de développement d’un navigateur, de commandes curl ou de scripts simples.

Voici le code vulnérable de la dernière version affectée (v15.2.2) :


 export const run = withTaggedErrors(async function runWithTaggedErrors(params) {
 const runtime = await getRuntimeContext(params)
 const subreq = params.request.headers[`x-middleware-subrequest`]        [1]
 const subrequests = typeof subreq === 'string' ? subreq.split(':') : [] [2]

 const MAX_RECURSION_DEPTH = 5
 const depth = subrequests.reduce(                                       [3]
  (acc, curr) => (curr === params.name ? acc + 1 : acc),
  0
 )

 if (depth >= MAX_RECURSION_DEPTH) {                                     [4]
  return {
     waitUntil: Promise.resolve(),
     response: new runtime.context.Response(null, {
       headers: {
         'x-middleware-next': '1',
       },
     }),
   }
 }
 

À l’étape [1], l’en-tête x-middleware-subrequest est récupéré dans la requête.
À l’étape [2], sa valeur est divisée à l’aide du délimiteur :. Une fonction reduce compte ensuite, à l’étape [3], le nombre d’éléments de ce tableau (subrequests) qui correspondent au nom de fichier du middleware.
Si ce nombre est supérieur ou égal à MAX_RECURSION_DEPTH (dont la valeur est 5) à l’étape [4], la fonctionnalité du middleware est contournée et la requête est dirigée vers sa route.

Valeurs possibles de l’en-tête d’attaque

Comme expliqué précédemment, le nom de l’en-tête vulnérable est x-middleware-subrequest. La valeur qui lui est attribuée dépend de Next.js, car elle est définie en fonction de la valeur de middlewareInfo.name, qui correspond essentiellement au chemin du fichier middleware.js ou middleware.ts.

Avant la version 12.2, le fichier du middleware s’appelait _middleware.js ou _middleware.ts et pouvait se trouver à n’importe quel niveau du sous-répertoire auquel nous tentions d’accéder. Dans notre cas, nous cherchons à accéder à /admin/dashboard. La valeur de middlewareInfo.name pouvait donc être pages/_middleware ou pages/admin/_middleware. Si dashboard avait été configuré comme un répertoire contenant un fichier index.js, cette valeur aurait également pu être pages/admin/dashboard/_middleware.

Par exemple, si nous avions utilisé notre code de démonstration avec une version de Next.js antérieure à la version 12.2, nous aurions dû déplacer middleware.js dans le répertoire pages et le renommer _middleware.js. Notre requête HTTP « malveillante » aurait alors été la suivante :


 GET /admin/dashboard HTTP/1.1
 x-middleware-subrequest: pages/_middleware
 

À partir de la version 12.2 et jusqu’à la version 13, le fichier du middleware doit se trouver à la racine du projet et porter le nom middleware.js/middleware.ts. Pour attaquer ces versions de Next.js, la charge utile de l’en-tête serait donc simplement middleware, et nous savons avec certitude que le fichier se trouve dans le répertoire racine.

Si nous avions utilisé une version de Next.js comprise entre les versions 12.2 et 13, notre requête « malveillante » aurait été modifiée comme suit :


 GET /admin/dashboard HTTP/1.1
 x-middleware-subrequest: middleware
 

À partir de la version 13 de Next.js, le contrôle de récursivité présenté précédemment a été mis en œuvre. Un pirate doit donc attribuer à l’en-tête malveillant la valeur middleware:middleware:middleware:middleware:middleware afin de simuler cinq niveaux de récursivité.

Notre PoC utilisant cette version, voici un extrait de la requête employée :


 GET /admin/dashboard HTTP/1.1
 x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware
 

Gardez à l’esprit que, dans tous les cas, le code du middleware pouvait se trouver dans un répertoire src. Pour exploiter la vulnérabilité, il aurait alors été nécessaire d’ajouter src au début des valeurs présentées précédemment. Par exemple, si nous avions placé le code de notre PoC dans un répertoire src, notre charge utile aurait dû être la suivante :


 GET /admin/dashboard HTTP/1.1
 x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware.
 

Exploitation de la CVE-2025-29927

Comme toujours, il est préférable d’observer une exploitation complète de la vulnérabilité afin de comprendre quelles instances de Next.js seraient vulnérables.

Nous avons mis en place notre propre site web de PoC avec l’arborescence suivante :

├── middleware.js
├── package-lock.json
├── package.json
└── pages
├── admin
│   └── dashboard.js
└── index.js

Tout d’abord, notre page de connexion :

Voici ce qui se passe lorsqu’un utilisateur non administrateur tente de se connecter :

Voici le tableau de bord d’administration accessible à l’adresse /admin/dashboard avec les identifiants appropriés :

Passons à l’exploitation : essayons d’abord d’envoyer une requête GET à /admin/dashboard sans l’en-tête malveillant :

Nous recevons une réponse 401 Unauthorized, car notre middleware s’active et constate qu’il ne s’agit pas d’un compte administrateur :

Essayons maintenant de répéter la même opération en ajoutant l’en-tête x-middleware-subrequest :

Nous recevons une réponse 200 OK !

Grâce à l’aperçu web, nous pouvons également constater que nous avons bien reçu le document présenté précédemment :

Correction de la CVE-2025-29927

Mise à niveau de la version

La meilleure façon de corriger la CVE-2025-29927 consiste à mettre à niveau votre version de Next.js vers l’une des versions corrigées :

  • 15.2.3
  • 14.2.25

Veillez à identifier toutes les versions potentiellement vulnérables, de la version 11.1.4 à la version 13.5.6 incluse, ainsi que les versions 14.2.24 et 15.2.2, puis à les remplacer par cette nouvelle version corrigée.

Blocage de l’en-tête vulnérable sur le serveur web

S’il n’est pas possible d’effectuer la mise à niveau, vous pouvez atténuer la vulnérabilité en configurant votre serveur web de manière à supprimer l’en-tête x-middleware-subrequest des requêtes entrantes.

Dans Apache, ajoutez la directive suivante au fichier .htaccess (mod_headers doit être installé et activé) :

 <IfModule mod_headers.c>
   RequestHeader unset x-middleware-subrequest
 </IfModule>

Dans NGINX, modifiez le fichier nginx.conf et ajoutez la directive proxy_set_header suivante au bloc server :

 proxy_set_header x-middleware-subrequest "";

Par exemple :

 server {
   listen 80;
   server_name your_domain.com;
   location / {
     proxy_set_header x-middleware-subrequest "";
   }
 }

Dans Express.js, ajoutez la directive suivante à votre code source JavaScript :

 // Middleware permettant de supprimer l’en-tête x-middleware-subrequest
 app.use((req, res, next) => {
   delete req.headers['x-middleware-subrequest'];
   next();
 });

Blocage de l’en-tête vulnérable à l’aide d’un WAF

S’il n’est pas possible d’effectuer la mise à niveau, vous pouvez atténuer la vulnérabilité en utilisant un pare-feu d’applications web afin de bloquer les requêtes contenant l’en-tête HTTP x-middleware-subrequest.

Correction de la CVE-2025-29927 avec JFrog Xray et JFrog Advanced Security

Comme toujours, JFrog Security Essentials (Xray) permet d’identifier chaque occurrence de Next.js dans l’ensemble de votre base de code et de vos artefacts compilés, notamment les conteneurs Docker, les packages de dépôts et même les fichiers binaires autonomes.

JFrog Advanced Security a également été mis à jour avec un scanner d’analyse contextuelle qui vérifie automatiquement si votre déploiement Next.js est réellement vulnérable à la CVE-2025-29927, en déterminant si un middleware Next.js est utilisé.


Plateforme JFrog : analyse contextuelle JFrog de la CVE-2025-29927 dans Next.js (cliquez sur l’image pour l’afficher en taille réelle)

Consultez le centre de recherche en sécurité de JFrog pour en savoir plus sur les dernières CVE, vulnérabilités et correctifs.