← Guias por stack

Next.js

Segurança para a tua app Next.js

O Next.js facilita misturar código de servidor e de cliente, e é aí que se colam a maioria das falhas: uma variável NEXT_PUBLIC a mais, uma API route sem proteção ou uns source maps em produção. Analisa a tua app e tira as dúvidas em 30 segundos.

Riscos típicos em Next.js

Segredos no bundle por causa do NEXT_PUBLIC

Tudo o que tem o prefixo NEXT_PUBLIC_ vai parar ao navegador. Uma chave privada aí fica exposta para sempre a quem abrir as DevTools.

API routes sem autorização

Uma API route é um URL público. Se só escondes o botão na interface mas não verificas a sessão no handler, qualquer um pode chamá-la diretamente.

Source maps e cabeçalhos por padrão

O Next.js não adiciona cabeçalhos de segurança por ti, e muitos builds publicam source maps que deixam reconstruir o teu código. As duas coisas resolvem-se no next.config.

Quase todos os buracos de uma app Next.js feita com IA vêm de uma única confusão: não saber que parte do código corre no servidor e que parte acaba no navegador. O Next.js mistura as duas no mesmo projeto, e o Cursor, o v0 ou o Bolt atravessam a fronteira sem avisar. Este guia explica esse modelo mental em cinco minutos, repassa o que as ferramentas de IA fazem mal no Next.js, deixa-te um bloco de regras para colar no teu projeto, um prompt de revisão e quatro verificações de fora. A lista ponto por ponto do que corrigir está na checklist de Next.js antes de lançar; aqui vai o porquê.

Parte 1: onde corre cada coisa

Cinco lugares, dois mundos

No App Router há cinco sítios onde o teu código pode viver: Server Components (só servidor, nunca chegam ao navegador), Client Components (marcados com "use client", enviados inteiros ao navegador), Route Handlers (app/api/.../route.ts, URLs públicos), Server Actions (funções com "use server" que o cliente invoca por POST) e o middleware (chamado proxy nas versões mais recentes), que corre antes de cada pedido. Os três últimos e os Server Components são o mundo do servidor; os Client Components são o mundo do navegador. Tudo o que importas num Client Component, incluindo constantes e funções auxiliares, viaja para o bundle.

O que chega ao navegador

  • Variáveis de ambiente com prefixo NEXT_PUBLIC_, embutidas no momento do build. As restantes só existem no servidor.
  • Qualquer dado que um Server Component passe como prop a um Client Component. Se passas o objeto user completo, viaja com o hash da palavra-passe e o email.
  • Os ficheiros da pasta public/, tal e qual.
  • Os source maps, se os ativares com productionBrowserSourceMaps.

Três mecanismos que evitam atravessar a fronteira

O pacote server-only: um import 'server-only' no início de um ficheiro faz o build falhar se alguém o importar a partir de um Client Component. Usa-o em tudo o que toque na base de dados ou leia segredos. Uma camada de acesso a dados: um módulo que centraliza a verificação de sessão e devolve só os campos necessários (um DTO), em vez de consultar a base de dados a partir de cada página. E a regra de que cada ponto de entrada verifica a sessão: Route Handlers, Server Actions e Server Components que leiam dados privados, cada um por si. O middleware não substitui essa verificação, como a CVE-2025-29927 demonstrou.

O que o Next.js não faz por ti

Não acrescenta cabeçalhos de segurança, não limita pedidos, não valida a entrada das Server Actions e não protege rotas só porque estão numa pasta chamada (admin). Tudo isso é código teu ou configuração no next.config.

Parte 2: o que a IA faz mal no Next.js

  • Tudo com "use client". Quando um componente precisa de estado, a IA marca-o como cliente e arrasta com ele a consulta à base de dados ou a chave da API. Divide: o componente de servidor obtém os dados, o de cliente só desenha.
  • Proteção só no middleware. O middleware redireciona se não houver cookie e o handler confia nisso. Verifica a sessão também no handler; foi o que a CVE do middleware ensinou, e versões anteriores a 15.2.3 ou 14.2.25 continuam vulneráveis.
  • Route Handlers e Server Actions sem autenticação nem validação. Uma Server Action é um endpoint público mesmo sem URL visível. Verifica quem chama e valida o corpo com um esquema (zod ou semelhante) antes de tocar em alguma coisa.
  • Segredos com prefixo público. NEXT_PUBLIC_OPENAI_KEY porque o componente de cliente "precisava". A chave vai para um Route Handler e o cliente chama o handler.
  • remotePatterns com wildcard. hostname: '**' na configuração de imagens transforma o teu otimizador de imagens num proxy aberto para qualquer URL.
  • Redirecionamentos com parâmetro. redirect(searchParams.next) sem verificar que o destino é uma rota interna: phishing com o teu domínio.
  • fetch a URLs do utilizador. Um handler que descarrega o que lhe passarem pode chegar a serviços internos da tua rede ou do fornecedor.
  • dangerouslySetInnerHTML com conteúdo de utilizador. XSS clássico; se precisas de HTML, sanitiza-o no servidor.
  • Sem cabeçalhos nem limites. Nem CSP, nem HSTS, nem X-Frame-Options, e um endpoint que chama um modelo pago sem teto por utilizador.

Um bloco de regras para o teu projeto

Cola-o no ficheiro de regras que a tua ferramenta lê (.cursor/rules, AGENTS.md ou equivalente) para que se aplique em cada geração:

Regras de segurança para este projeto Next.js:
- Os componentes são Server Components salvo se precisarem de estado ou eventos do navegador. Um Client Component nunca importa módulos que acedam à base de dados ou leiam process.env sem prefixo.
- Todo o módulo que toque na base de dados ou em segredos começa com import 'server-only'.
- Nunca uses NEXT_PUBLIC_ para uma chave secreta. As chamadas a serviços com chave vão num Route Handler ou numa Server Action.
- Cada Route Handler e cada Server Action verifica a sessão e valida a entrada com um esquema antes de fazer o que quer que seja. O middleware não conta como autenticação.
- Passa aos Client Components só os campos necessários, nunca o objeto completo do utilizador ou da linha.
- Os redirecionamentos só aceitam rotas internas que comecem por uma única barra.
- images.remotePatterns lista domínios concretos, nunca um wildcard de host.
- Não uses dangerouslySetInnerHTML com conteúdo de utilizador.
- O next.config define os cabeçalhos de segurança e não ativa productionBrowserSourceMaps.

Um prompt de revisão antes de fazer deploy

Revê a segurança desta app Next.js e não mudes nada ainda. Responde com uma lista:
1. Client Components que importem módulos de base de dados, leiam segredos ou recebam como prop objetos com campos sensíveis.
2. Route Handlers e Server Actions sem verificação de sessão ou sem validação de entrada.
3. Rotas cuja única proteção seja o middleware.
4. Variáveis NEXT_PUBLIC_ que contenham chaves secretas.
5. Redirecionamentos que aceitem um destino do utilizador, fetch a URLs do utilizador e usos de dangerouslySetInnerHTML.
6. remotePatterns com wildcard, productionBrowserSourceMaps ativado e cabeçalhos de segurança ausentes no next.config.
7. Versão do Next.js e se é anterior a 15.2.3 ou 14.2.25.
Para cada ponto, propõe a alteração exata e espera pela minha confirmação.

Verifica o resultado de fora

Quatro comandos contra o teu domínio. Cabeçalhos e versão do middleware:

curl -sI https://oteudominio.com | grep -iE "strict-transport|content-security|x-frame|x-content-type"
curl -s -o /dev/null -w "%{http_code}\n" -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" https://oteudominio.com/dashboard

Se o segundo devolver 200 numa rota que devia redirecionar para o login, a tua versão é vulnerável à CVE do middleware: atualiza hoje. Depois, source maps e rotas de API que o bundle revela:

curl -s https://oteudominio.com | grep -oE '/_next/static/chunks/[^"]+\.js' | head -3
curl -s https://oteudominio.com/_next/static/chunks/main-app-XXXX.js | grep -oE '"/api/[^"]+"' | sort -u

Pede cada rota de API sem sessão: o correto é um 401 ou 403. O Scanaris faz estas verificações e cerca de quarenta mais em 30 segundos: deteta que a app é Next.js e a sua versão, testa o cabeçalho da CVE, procura segredos nos chunks, verifica se os source maps estão publicados, revê cabeçalhos, CSP, cookies, CORS e ficheiros expostos, e dá-te um fix prompt por cada falha para colar no Cursor ou no v0. Se fazes deploy na Vercel, o guia da Vercel cobre as previews públicas e as variáveis de ambiente.

Perguntas frequentes

As Server Actions são seguras por defeito?

São mais difíceis de descobrir do que um Route Handler, mas igualmente públicas: qualquer pessoa com o identificador da ação pode invocá-la. Trata-as como um endpoint: sessão e validação dentro da função.

Basta o middleware para proteger o painel?

Não. Serve para redirecionar depressa, mas a verificação real vai em cada página, handler e ação. A CVE-2025-29927 permitia saltar o middleware com um cabeçalho; mesmo numa versão corrigida, a regra continua a ser a mesma.

Posso continuar a usar o Pages Router?

Sim, e o modelo é o mesmo: getServerSideProps e pages/api são o servidor, o resto é cliente. Devolve de getServerSideProps só o que a página precisa, porque tudo o que devolves é serializado no HTML.

Verificações relacionadas

A tua app Next.js passa nestas verificações?

Analisa-a grátis e recebe um fix prompt por cada problema que encontrarmos.

Analisar o meu site grátis