← Voltar ao blog
SegurançaScanaris Team · 8 min de leitura · October 04, 2026

Checklist de segurança para a tua app Next.js antes de lançar

Lançar uma app Next.js com o Cursor, o v0 ou o Bolt é rápido, mas a velocidade esconde falhas que não vês até alguém as encontrar por ti. Esta checklist percorre o que há a rever antes de carregares em deploy, com o porquê de cada ponto, como o verificar e o código para o corrigir. No fim tens a versão de dois minutos.

Como o Next.js pensa a fronteira entre servidor e cliente

Quase todas as falhas de segurança no Next.js são a mesma falha: algo que devia ficar no servidor atravessou para o browser. Os Server Components executam no servidor e nunca enviam o seu código para o cliente; assim que um ficheiro leva 'use client', tudo o que importa acaba no bundle público. Os Route Handlers (app/api/*/route.ts) e as Server Actions são URLs públicos mesmo que não os vejas. O middleware corre antes de tudo, mas não é uma muralha. Com essa fronteira clara, o resto da lista é mecânica.

1. Variáveis de ambiente: cuidado com NEXT_PUBLIC

Porque importa. Tudo o que começa por NEXT_PUBLIC_ é embutido no JavaScript do browser no momento do build. Qualquer pessoa o lê com as ferramentas de programador. Nunca ponhas aí uma chave de API privada, um token de serviço nem o segredo da tua base de dados.

Como verificar. Abre o teu .env e o painel da Vercel e lê cada variável com prefixo público a perguntar-te: acontecia alguma coisa se a publicasse no Twitter? Se a resposta é sim, tira-lhe o prefixo e passa-a para o servidor.

Como corrigir. As variáveis sem prefixo só existem no servidor: lê-as a partir de Server Components, Route Handlers ou Server Actions. Para que um módulo com segredos nunca possa ser importado a partir de um componente de cliente, acrescenta import 'server-only' na primeira linha: se alguém o importar do lado errado, o build falha em vez de deixar fugir a chave. Mais detalhe em os segredos que a tua app deixa fugir no browser.

2. Route Handlers e Server Actions: valida e autoriza sempre

Porque importa. Uma rota de API não é privada por estar na tua pasta. É um URL público que qualquer pessoa pode chamar com curl. E uma Server Action, mesmo que seja invocada a partir de um botão, também: o Next.js expõe-a como um endpoint POST com um identificador. Um botão que não aparece a um utilizador não impede que alguém bata no endpoint diretamente.

Como corrigir. Verifica a sessão e as permissões dentro de cada handler e de cada action, não só na interface. Valida o corpo do pedido com um esquema (zod ou semelhante) antes de tocar na base de dados. Nunca aceites o identificador do utilizador vindo do cliente: tira-o da sessão. E põe um limite de pedidos ao que custe dinheiro ou envie emails.

// app/actions/update-profile.ts
'use server'
import { z } from 'zod'
import { getSession } from '@/lib/auth'

const Schema = z.object({ name: z.string().min(1).max(80) })

export async function updateProfile(input: unknown) {
  const session = await getSession()
  if (!session) throw new Error('Unauthorized')
  const data = Schema.parse(input)
  // usa session.user.id, nunca um id que venha do cliente
  await db.user.update({ where: { id: session.user.id }, data })
}

3. O middleware não é a tua única autenticação

Porque importa. É tentador proteger todo o /dashboard a partir do middleware.ts e esquecer o assunto. Em março de 2025 foi publicada a CVE-2025-29927: um header interno (x-middleware-subrequest) permitia saltar o middleware por completo nas versões afetadas, e com ele qualquer verificação de sessão que vivesse só ali. Foi corrigida no Next.js 15.2.3 e 14.2.25 (com patches para 13 e 12), mas a lição fica.

Como corrigir. Atualiza o Next.js para uma versão corrigida e usa o middleware como primeira camada (redirecionar quem não tem sessão), nunca como a única. A verificação que protege mesmo os dados vai na página, no handler ou na action que os serve.

4. Headers de segurança

Porque importa. Por defeito o Next.js não envia headers defensivos. Sem eles a tua app fica exposta a clickjacking, a que o browser execute como script o que não o é e a downgrade para HTTP.

Como corrigir. No next.config.js:

// next.config.js
const securityHeaders = [
  { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
  { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
  { key: 'X-Content-Type-Options', value: 'nosniff' },
  { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
  { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
]

module.exports = {
  poweredByHeader: false,
  productionBrowserSourceMaps: false,
  async headers() {
    return [{ source: '/(.*)', headers: securityHeaders }]
  },
}

A Content-Security-Policy merece tratamento à parte: o Next.js injeta scripts inline para hidratar a página, por isso uma CSP rigorosa precisa de um nonce gerado no middleware e passado aos componentes. Começa em modo Report-Only. O detalhe de cada header está em os headers de segurança explicados para humanos.

5. Segredos que atravessam para Client Components

Porque importa. É fácil uma chave privada acabar num componente de cliente por engano, sobretudo quando a IA reescreve ficheiros e move imports. Se aparece no JavaScript servido, já está comprometida.

Como verificar. Depois de next build, procura em .next/static strings como sk_live, service_role, sk-ant ou URLs de webhooks. Se aparecerem, roda-as e passa-as para o servidor com import 'server-only' como seguro.

6. Imagens remotas e pedidos a URLs do utilizador

Porque importa. O next/image otimiza imagens através do teu servidor. Se em images.remotePatterns permitires qualquer host, qualquer pessoa pode usar o teu servidor como proxy de imagens e gastar a tua quota. O mesmo com uma rota de API que descarrega o URL que o utilizador lhe passa: pode apontar para serviços internos da tua infraestrutura (SSRF).

Como corrigir. Limita remotePatterns aos domínios que usas mesmo. Se uma rota tiver de descarregar URLs externos, valida o protocolo (só https), rejeita IPs privados e nomes internos, e põe um tempo máximo.

7. Redirecionamentos abertos

Porque importa. O clássico redirect(searchParams.next) depois do login permite construir links do teu domínio que acabam num site de phishing: oteudominio.com/login?next=https://mau.example.

Como corrigir. Aceita só caminhos relativos que comecem por / (e não por //), ou compara com uma lista de destinos permitidos.

8. Ficheiros que não deviam estar acessíveis

Porque importa. Tudo o que está em public/ é servido tal e qual: um .env copiado para lá por engano, um dump da base de dados ou um service-account.json ficam à distância de um URL. E os source maps em produção permitem ler o teu código de cliente com os nomes originais.

Como verificar. Experimenta oteudominio.com/.env, /.git/HEAD e abre um ficheiro JS do bundle para ver se termina numa linha sourceMappingURL a apontar para um .map acessível. Olha para a pasta public/ com os olhos de um desconhecido.

9. Cookies de sessão e bibliotecas de autenticação

Porque importa. O Auth.js (NextAuth), o Clerk ou o Supabase com o pacote para servidor configuram bem as cookies por defeito. O que falha é o que acrescentas tu: uma cookie própria sem HttpOnly, um AUTH_SECRET fraco ou copiado de um tutorial, ou a sessão guardada em localStorage.

Como corrigir. Gera o segredo com openssl rand -base64 32, guarda-o sem prefixo público, e para qualquer cookie própria usa Secure, HttpOnly e SameSite=Lax.

10. Dependências e a versão do Next.js

Porque importa. A tua app arrasta centenas de pacotes, e o próprio Next.js publica correções de segurança várias vezes por ano. O caso do middleware de 2025 afetou quem não atualizava.

Como corrigir. npm audit antes de cada publicação, Dependabot ou Renovate no repositório, e uma regra simples: atualizar o Next.js no mesmo mês em que sai um patch de segurança.

Publicação na Vercel: três detalhes

  • Ambientes. As variáveis têm âmbito (Production, Preview, Development). Não dês às publicações de preview as credenciais de produção: um preview é um URL público com o teu código mais recente.
  • Proteção dos previews. Ativa a Deployment Protection para que os URLs de preview exijam login da Vercel; senão, qualquer pessoa com o link vê o branch em curso.
  • Headers. Os do next.config.js aplicam-se na Vercel sem mais; se também usares vercel.json, não dupliques.

A tua checklist de 2 minutos

  • Nenhuma variável NEXT_PUBLIC_ contém um segredo; os módulos com chaves levam import 'server-only'.
  • Cada Route Handler e Server Action verifica a sessão e valida a entrada; o id do utilizador vem da sessão.
  • Next.js numa versão corrigida; o middleware não é a única camada de auth.
  • Headers de segurança no next.config.js; poweredByHeader: false; CSP pelo menos em modo de relatório.
  • Bundle sem sk_live, service_role nem webhooks; source maps desativados.
  • remotePatterns limitados; nada descarrega URLs do utilizador sem validar.
  • Redirecionamentos só para caminhos relativos.
  • public/ sem ficheiros sensíveis; .env e .git inacessíveis.
  • Cookies com Secure, HttpOnly e SameSite; AUTH_SECRET aleatório.
  • npm audit limpo; previews protegidos e sem segredos de produção.

Verifica tudo isto em 30 segundos

Rever esta lista à mão em cada publicação é aborrecido e esquece-se. O Scanaris faz verificações só de leitura sobre o teu site publicado: headers, segredos expostos no JavaScript, ficheiros sensíveis acessíveis, source maps, cookies e CORS. Cada resultado chega com um prompt pronto a colar no Cursor ou no v0 com a correção exata para Next.js. Se o deixares em monitorização, avisa-te quando uma sessão de vibe coding voltar a abrir algo. Para aprofundar na tua stack, há a página de segurança para Next.js e a checklist geral de lançamento.

Perguntas frequentes

As Server Actions são seguras por defeito?

São mais cómodas do que uma rota de API, não mais seguras. O Next.js expõe-as como endpoints públicos; a autenticação e a validação pões-las tu dentro de cada uma.

O middleware protege as minhas rotas?

Serve para redirecionar e para verificações baratas, mas não deve ser a única barreira. Depois do caso de 2025, a regra é verificar a sessão também onde os dados são servidos.

Preciso de CSP se uso Next.js?

Sim, mas com nonce, e a começar em modo de relatório. Sem nonce, uma CSP rigorosa bloqueia os scripts inline da própria framework e a página fica em branco.

Como está o teu site?

Passa-lhe o Scanaris e verifica em 30 segundos, grátis.

Analisar o meu site

Verificações relacionadas

Guias de segurança por stack