CVE-2025-55183: Cuando tu Server Function de Next.js devuelve su propio código fuente
Una petición maliciosa hacía que las Server Functions de Next.js devolvieran su código fuente en la respuesta HTTP. Si tenías una API key hardcodeada — aunque fuera 'solo para probar' — era legible.
Enrique Alvarez
Security Engineer
En el mundo de los CVEs de seguridad, los números CVSS mandan la atención. Un CVSS 10 como React2Shell (CVE-2025-55182) entra con sirenas y todo el mundo actualiza. Un CVSS 5.3 suena a "severidad media" y mucha gente lo ignora.
CVE-2025-55183 fue eso: el CVE callado del cluster de React2Shell. Ningún RCE, ningún shell remoto, ningún headline que gritara "actualiza ahora". Solo una petición HTTP diseñada que hacía que tu Server Function devolviera su propio código fuente en la respuesta.
El problema no fue técnico — fue de hábito. Cursor escribió tu Server Action con una API key de placeholder. Copilot sugirió el patrón const API_KEY = 'sk-proj-...' y pusiste la tuya. Claude te dio el boilerplate completo "solo reemplaza la key". Y muchos developers, con deadline encima y app funcionando, deployaron sin hacer ese reemplazo. Con CVE-2025-55183, cualquier atacante con la petición correcta podía leer ese literal de cadena directamente en la respuesta HTTP.
Qué es CVE-2025-55183 (y qué no es)
CVE-2025-55183 es una vulnerabilidad de divulgación de información en Next.js App Router. CVSS 5.3 — severidad media.
No es ejecución remota de código. No permite tomar el servidor. No lee tu base de datos ni tus variables de entorno.
Lo que sí hace: en condiciones específicas, una petición HTTP maliciosa puede provocar que una Server Function devuelva fragmentos de su propio código fuente dentro del cuerpo de la respuesta.
El mecanismo está en el protocolo React Flight — el formato de serialización que Next.js usa para comunicar Server Components y Server Actions con el cliente. Cuando el servidor procesa una petición de Server Function, serializa la respuesta usando este protocolo. La falla permitía manipular esa serialización para que incluyera el texto del código fuente de la función en lugar de — o junto con — la respuesta esperada.
Lo que queda expuesto son literales de cadena en el código fuente. String constants. Variables declaradas con un valor hardcodeado. No referencias de runtime como process.env.KEY — esas siguen siendo seguras. Solo los valores escritos directamente en el archivo.
Los secretos cargados desde variables de entorno con
process.env.API_KEYno estuvieron expuestos. El problema es específicamente con string literals:const API_KEY = 'sk-prod-abc123'.
Versiones afectadas: Las mismas que el cluster React2Shell — Next.js 14.x por debajo de 14.2.35 y Next.js 15.x por debajo de 15.2.4.
Fix: Actualizar a Next.js 14.2.35+ o 15.2.4+.
Qué ve un atacante exactamente
Imagina esta Server Function en tu proyecto:
// app/actions/reports.js
'use server'
// MAL: literal de cadena — queda expuesto con CVE-2025-55183
const OPENAI_API_KEY = 'sk-proj-abc123xyz987...'
const INTERNAL_WEBHOOK = 'https://hooks.internal.company.com/alerts?token=secret-token-prod'
export async function generarResumen(texto) {
const res = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: 'gpt-4o', messages: [{ role: 'user', content: texto }] }),
})
return res.json()
}Un atacante que aprovecha CVE-2025-55183 no necesita encontrar un endpoint documentado ni hacer fuzzing de rutas. Manda una petición especialmente diseñada al endpoint de la Server Function y la respuesta puede incluir el código de la función — incluyendo sk-proj-abc123xyz987... y la URL del webhook interno.
Con esa key de OpenAI puede generar tokens a tu costa. Con la URL interna puede investigar tu infraestructura. Y todo sin activar un solo log de autenticación fallida, porque nunca intentó autenticarse — tu propio servidor le mandó los datos.
La línea de código que lo causó
No fue una falla exótica. Fue el patrón más común de "lo arreglo después" que existe en el desarrollo con IA.
Mira la diferencia:
// app/actions/ai.js
'use server'
// MAL: string literal hardcodeado — vulnerable a CVE-2025-55183
const OPENAI_API_KEY = 'sk-proj-abc123xyz...'
export async function resumirTexto(input) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: { Authorization: `Bearer ${OPENAI_API_KEY}` },
// ...
})
return response.json()
}// app/actions/ai.js
'use server'
// BIEN: referencia de runtime — el valor nunca existe como literal en el código fuente
export async function resumirTexto(input) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
// ...
})
return response.json()
}La distinción técnica es importante: process.env.OPENAI_API_KEY es una referencia que se resuelve en tiempo de ejecución. El valor nunca está escrito en tu código fuente. CVE-2025-55183 solo puede exponer lo que está escrito — los literales.
const KEY = 'sk-proj-abc123' está escrito. Es un literal. Eso es lo que la falla filtra.
Cómo los asistentes de IA generan este patrón por defecto
Esta es la parte que hace a CVE-2025-55183 más relevante de lo que su CVSS sugiere.
Los asistentes de código — Cursor, GitHub Copilot, v0, Claude — generan Server Actions con frecuencia usando el patrón de placeholder hardcodeado. No por negligencia: es para que el código sea ejecutable de inmediato, sin que el developer tenga que configurar nada antes de ver que funciona.
Un prompt como "crea una Server Action que llame a la API de OpenAI para resumir texto" casi siempre genera algo así:
'use server'
const OPENAI_API_KEY = 'tu-api-key-aqui' // Reemplaza con tu key real
export async function summarize(text: string) {
// ...
}El comentario dice "reemplaza con tu key real". Pero en la práctica:
- El developer pone la key real para probar que funciona.
- La función funciona.
- El developer sigue con la siguiente tarea.
- El
// TODO: mover a .envnunca llega. - Se hace commit. Se deploya.
Estudiamos patrones en repos públicos de GitHub — el patrón const ... = 'sk-proj- dentro de archivos con 'use server' aparece con una frecuencia que incomoda. No son developers descuidados: son developers que van rápido con herramientas que generan código inseguro por default.
Data Hogo detecta exactamente este patrón — string literals que parecen secrets (API keys, tokens, contraseñas) dentro de archivos de Server Actions — como parte de sus 199 checks de seguridad. Si querés ver si tu repo tiene este problema antes de revisarlo manualmente: escanea tu repo gratis en datahogo.com.
Cómo auditar tus Server Functions ahora mismo
Dos pasos. Primero, verifica tu versión de Next.js:
npm list nextNecesitas ver 14.2.35 o superior, o 15.2.4 o superior. Si estás atrás:
npm install next@latestSegundo, busca string literals que parezcan secrets en tus archivos server. El grep de abajo no es perfecto — tiene falsos positivos — pero te da un punto de partida en menos de 30 segundos:
# Encuentra archivos con 'use server' que también contengan patrones de secrets hardcodeados
grep -r "use server" . --include="*.ts" --include="*.tsx" --include="*.js" -l \
| xargs grep -l "sk-\|api_key\|API_KEY\|secret\|token\|password\|passwd"Los archivos que aparezcan en esa lista merecen revisión manual. Busca específicamente declaraciones de variable con string literals — no referencias a process.env.
Si encuentras algo así:
const STRIPE_SECRET = 'sk_live_abc123...'
const DB_PASSWORD = 'hunter2'
const WEBHOOK_TOKEN = 'whsec_xyzxyzxyz'Trátalos como comprometidos. Rota los credentials, revoca los anteriores, y mueve los nuevos a variables de entorno.
Tres cosas que hacer hoy
1. Actualiza Next.js si no lo has hecho.
npm install next@latestVerifica después:
npm list next
# next@15.2.4 o superior — bien
# next@15.1.x o inferior — actualiza2. Audita tus Server Actions en busca de literals hardcodeados.
El grep de arriba es el punto de partida. Después de identificar archivos sospechosos, la regla es simple: si el valor está escrito directamente en el código, muévelo a .env.local y accédelo con process.env.
3. Si encontraste un secret hardcodeado, rótalo — aunque hayas actualizado.
CVE-2025-55183 pudo haber estado activo en tu app antes de que actualizaras. Si el secret estuvo en el código durante ese tiempo, un atacante pudo haberlo leído. Actualizar Next.js cierra la falla, pero no deshace lo que ya fue expuesto.
La rotación es el paso que mucha gente omite porque "nadie nos atacó". Quizás no. Pero tampoco tendrías un log de eso — la explotación era pasiva, sin errores de autenticación, sin tráfico anormal evidente.
TL;DR
- CVE-2025-55183 es la hermana callada de React2Shell. CVSS 5.3, no CVSS 10. Sin RCE, pero con filtración de código fuente.
- Una petición HTTP maliciosa podía hacer que una Server Function devolviera string literals de su propio código — incluyendo API keys hardcodeadas.
process.env.API_KEYnunca estuvo en riesgo. Solo los valores escritos directamente en el código:const KEY = 'sk-proj-...'.- Los asistentes de IA (Cursor, Copilot, v0) generan este patrón inseguro por default. El developer que va rápido a menudo no hace el reemplazo antes de deployar.
- Fix: actualizar a Next.js 14.2.35+ o 15.2.4+.
- Si encontraste un literal hardcodeado: muévelo a
.env, rota el credential, y asume que pudo haber sido leído. - Los secrets en
process.envestán seguros. Los string literals directos en el código fuente no lo están.
Posts Relacionados
CVE-2025-67779: El parche de Next.js que necesitaba otro parche
El primer fix para CVE-2025-55184 era incompleto. CVE-2025-67779 es el parche del parche. Si actualizaste Next.js una vez después de React2Shell, es posible que todavía estés expuesto.
CVE-2025-55184: El DoS de loop infinito en Next.js que llegó con el parche de React2Shell
CVE-2025-55184 llegó en las mismas versiones de Next.js que corregían React2Shell. Una petición maliciosa desencadena un loop infinito que congela tu servidor — sin error, sin crash, solo silencio.
React2Shell: La vulnerabilidad crítica que afectó cada proyecto con Next.js App Router
CVE-2025-55182 permitió a atacantes ejecutar código arbitrario en tu servidor con una sola petición HTTP — CVSS 10. Si usas Next.js App Router con Server Actions, revisa tu versión ahora.