Volver al blog
Desarrollo

CVE-2025-29927: bypass de autorización en Next.js self-hosted

CVE-2025-29927 permite saltarse la autenticación de Next.js con una cabecera HTTP. Así funciona el bypass y por qué muchos self-hosted siguen expuestos.

Blurtek
6 min lectura889 palabras

El CVE-2025-29927 permite saltarse la autenticación de Next.js añadiendo la cabecera x-middleware-subrequest a cualquier petición HTTP. Afecta a versiones anteriores a 12.3.5, 13.5.9, 14.2.25 y 15.2.3, con CVSS 9.1 (NVD). No es ejecución remota de código: es un bypass de autorización (CWE-284) que da acceso directo a rutas protegidas sin pasar por el middleware. Muchos despliegues self-hosted siguen expuestos meses después del parche.

01

Qué es realmente el CVE-2025-29927 (y por qué no es un RCE)

Conviene aclarar esto de entrada porque la confusión es habitual y afecta a cómo se prioriza el arreglo. El CVE-2025-29927, registrado como GHSA-f82v-jwr5-mffw, está clasificado como CWE-284 (control de acceso inadecuado), no como ejecución de código arbitrario. El atacante no gana una shell ni inyecta código en el servidor: consigue que el servidor le trate como si ya hubiera pasado un control que en realidad nunca superó. La puntuación CVSS 9.1 es alta por la combinación de factores de explotación —vector de red, sin autenticación previa, complejidad baja— y no por la gravedad del payload, que es simplemente una cabecera HTTP con un valor concreto. Esa distinción importa para el CTO que decide con qué urgencia mueve equipos: sigue siendo crítico, pero el vector de ataque y la respuesta al incidente son distintos a los de un RCE clásico. En la práctica, cualquier ruta que dependa del middleware para decidir quién entra —paneles de administración, áreas de cliente, endpoints internos— queda accesible como si el visitante tuviera sesión válida.

El mecanismo que nadie explica: para qué sirve x-middleware-subrequest

La mayoría de artículos sobre este CVE se quedan en 'añade esta cabecera y entras', sin explicar por qué esa cabecera existe en primer lugar, y esa parte es la que explica el fallo de diseño. Next.js permite que el propio middleware dispare una subpetición interna —por ejemplo, al reescribir una ruta que vuelve a pasar por el mismo árbol de middleware— y necesitaba una forma de evitar que esa subpetición desencadenara el middleware otra vez de forma infinita. La solución fue etiquetar la petición internamente con una cabecera que enumera los middlewares ya ejecutados en esa cadena, de modo que si el motor detecta que ya se ha procesado, se salta la ejecución y sigue directo al destino. El problema es que esa cabecera viajaba en los headers HTTP normales, sin ningún mecanismo que garantizara que solo el propio runtime de Next.js podía escribirla. Un cliente externo podía fabricar esa misma cabecera a mano, con el valor documentado públicamente en el aviso de seguridad, y conseguir exactamente el mismo efecto: que el servidor se salte el middleware por completo, incluida cualquier comprobación de sesión o rol que viviera ahí dentro.

02

Cómo funciona el bypass paso a paso

  • El atacante identifica una instancia Next.js en el rango de versiones vulnerables (build ID, cabeceras de respuesta, comportamiento de rutas).
  • Envía una petición HTTP directa a una ruta protegida (por ejemplo /admin o /api/interno) añadiendo la cabecera x-middleware-subrequest.
  • Next.js interpreta que la petición ya ha atravesado el middleware en esa cadena de ejecución y no vuelve a invocarlo.
  • Cualquier lógica de autenticación, redirección a login o comprobación de rol definida solo en middleware.ts se omite por completo.
  • La petición llega directa al route handler o a la página protegida, con el mismo resultado que si el usuario tuviera una sesión válida.
03

Autohospedado vs Vercel gestionado: la verdad incómoda

Aquí está el dato que casi nadie pone en contexto: Vercel, la plataforma que mantiene Next.js, no dependió únicamente del parche de código para proteger a sus clientes. Su infraestructura de edge normaliza y controla las cabeceras internas antes de que la petición llegue al código de la aplicación, lo que en la práctica neutralizaba buena parte de los intentos de inyectar x-middleware-subrequest desde fuera, incluso en versiones sin actualizar. Los despliegues autohospedados —contenedores Docker con next start, servidores Node standalone, instalaciones detrás de un nginx o Traefik genérico— no tienen esa capa intermedia salvo que alguien la haya construido a propósito. Para esas instalaciones, la única barrera real siempre fue el código de Next.js, y mientras ese código tuviera el fallo, cualquier petición HTTP normal bastaba. Esto explica por qué, meses después de publicarse las versiones corregidas, sigue habiendo instancias self-hosted sin actualizar: el equipo que las mantiene no vivió ninguna alerta ni ningún fallo visible, porque la explotación no rompe nada, simplemente concede acceso silencioso.

La falsa sensación de seguridad heredada de Vercel

Hay un efecto colateral menos comentado todavía: los equipos que desarrollan y prueban su aplicación en Vercel y después migran a un despliegue propio —por coste, por residencia de datos, por requisitos de cumplimiento— arrastran la sensación de que 'esto ya está probado y es seguro'. Esa confianza se construyó mientras la infraestructura de Vercel absorbía en silencio parte del riesgo, no porque el código de la aplicación fuera especialmente robusto. Al migrar a un servidor propio, esa protección invisible desaparece sin ningún aviso ni cambio de comportamiento visible: la aplicación sigue funcionando igual, solo que ahora cualquier petición HTTP con la cabecera adecuada consigue lo que antes se bloqueaba en el borde de red. Es una lección incómoda sobre dar por hecho que las propiedades de seguridad de una plataforma gestionada viajan con el código cuando cambias de infraestructura.

04

El problema real: el middleware nunca debió ser tu única barrera de autorización

Aquí toca ser honestos incluso a costa de sonar menos vendedores: parchear la versión de Next.js es obligatorio, pero si la única comprobación de sesión o de rol de tu aplicación vive en middleware.ts, este CVE concreto deja de ser el problema y pasa a ser un síntoma. El middleware de Next.js corre en un runtime edge limitado, pensado para redirecciones y reescrituras rápidas, no como sustituto de una capa de autorización a nivel de dato. La propia documentación de Next.js recomienda ahora explícitamente revalidar la autorización en la capa de acceso a datos —en cada Server Component, en cada route handler— precisamente porque ya ha quedado demostrado que el middleware se puede saltar, sea por un bug como este o por particularidades de cómo se resuelven ciertas rutas. No hace falta un CVE nuevo para que vuelva a pasar: basta con que alguien encuentre otra forma de convencer al framework de que esa petición ya pasó el filtro.

Actualizar la versión es la parte fácil. Lo difícil es aceptar que si la autorización solo vive en un sitio, cualquier fallo en ese sitio te deja sin nada. Se comprueba donde se lee el dato, no solo a la entrada.

Blurtek
05

Cómo comprobar si tu despliegue está expuesto

  • Revisa la versión de Next.js en package.json y en .next/BUILD_ID de cada despliegue activo, no solo en el repositorio.
  • Si el despliegue es self-hosted y usa una versión anterior a 12.3.5, 13.5.9, 14.2.25 o 15.2.3, considérala expuesta hasta que actualices.
  • Actualiza a la versión parcheada correspondiente a tu rama mayor; no hace falta saltar de versión mayor para corregir esto.
  • Si no puedes actualizar de inmediato, bloquea o elimina la cabecera x-middleware-subrequest en el proxy inverso (nginx, Traefik, tu balanceador) antes de que llegue a la aplicación.
  • Localiza toda la lógica de autorización que vive solo en middleware.ts y replícala como comprobación explícita en cada route handler o Server Component que sirva datos sensibles.
CVSS 9.1

Puntuación de severidad crítica asignada al CVE-2025-29927 (NVD, 2025)

Si mantienes un despliegue Next.js self-hosted y no tienes claro si el middleware es tu única barrera de autorización, en Blurtek revisamos la configuración y la arquitectura de autorización antes de que el problema lo encuentre otro.

Solicitar diagnóstico