Pular para o conteúdo

Segurança

Regras universais, válidas em toda ADR de todo projeto.

  • Nunca commitar .env.local ou qualquer arquivo com segredos.
  • Não expor segredos no frontend. Chaves sensíveis só no servidor.
  • Não logar tokens, chaves de API, payloads sensíveis ou dados confidenciais.
  • Não acessar banco de produção durante o desenvolvimento.
  • Não deletar arquivos, pastas, tabelas, colunas, dados ou configurações sem autorização explícita.
  • Dados sensíveis reais (creators, contratos) não entram em resources/ versionado sem cuidado — preferir anonimização ou referência.
  • Autenticação antes de qualquer operação protegida.
  • Validação Zod em toda entrada de API (princípio 7).
  • Tipagem total para fechar classes inteiras de erro (princípio 6).

Estar autenticado não é estar autorizado. Toda rota que retorna ou modifica dados precisa checar, explicitamente, se aquele usuário pode acessar aquele recurso. Autenticação responde “quem é”; autorização responde “tem direito a isso”. A segunda checagem nunca é dispensável, mesmo que a primeira tenha passado.

A classe de bug mais comum e mais grave em APIs é o IDOR (Insecure Direct Object Reference): o endpoint confia que o ID na URL “pertence” a quem está logado. Um usuário comum chama GET /api/orders/42 e recebe o pedido de outra pessoa. Ou chama GET /api/users e recebe a lista inteira — endpoint que só admin deveria enxergar. Nada disso é hipotético.

  • Cada rota declara o escopo que exige (papel, dono do recurso, tenant) e checa esse escopo antes de ler/escrever — não depois.
  • Filtrar por dono no próprio query do Prisma, não na resposta. where: { id, userId: session.userId } em vez de buscar pelo id e conferir o userId depois. Filtrar depois é exatamente o caminho que vaza dados em listagens.
  • Papel/escopo nunca vem do cliente. Vem da sessão no servidor. Header, query string ou campo do body dizendo role=admin é entrada do usuário — trate como tal.
  • Listagens são filtradas no servidor pelo escopo do usuário. Nunca devolva “tudo” e deixe o frontend esconder. O que o cliente não pode ver, o servidor não envia.
  • Rotas de admin ficam separadas e checam papel explicitamente (ex.: /api/admin/... exigindo session.role === 'admin'). Não basta ocultar o link no menu.
  • Erro padrão é negar. Em dúvida, 403. Se a rota não checou escopo, ela está errada — não importa o quanto a UI “garante” que o usuário nunca chegaria ali.
// errado: confia no ID da URL
const order = await prisma.order.findUnique({ where: { id } });
return Response.json(order);

// certo: o escopo do dono entra no where
const order = await prisma.order.findFirst({
  where: { id, userId: session.userId },
});
if (!order) return new Response(null, { status: 404 });
return Response.json(order);

A diferença não é estilística — é a fronteira entre “API funcional” e “vazamento de dados de outro usuário”.

Esta checagem é da rota (ver Backend e API). O middleware base autentica; quem autoriza a operação específica sobre o recurso específico é a própria rota, porque só ela conhece o domínio.

Criado por Joseph Trupel