Pensar como um atacante
Uma API publicada recebe requisições de qualquer um. Assuma que toda entrada é hostil até que você a valide. O projeto OWASP mantém a lista dos riscos mais habituais; estes são os básicos que você deve conhecer.
Injeção
Ocorre quando dados do usuário são interpretados como código/comandos. O caso clássico é a injeção SQL:
// RUIM: o usuário controla parte da consulta.
db.query("SELECT * FROM users WHERE name = '" + nome + "'");
// Se nome = "' OR '1'='1", a condição é sempre verdadeira.
// BOM: consultas parametrizadas. O motor trata o valor como dado, não código.
db.query("SELECT * FROM users WHERE name = $1", [nome]);
A defesa geral: nunca construa comandos concatenando texto do usuário; use parâmetros, prepared statements ou um ORM.
XSS (Cross-Site Scripting)
Se você guarda um comentário como <script>roubarCookies()</script> e depois o
exibe tal como está no HTML, esse script roda no navegador de outros
usuários. A defesa é escapar/sanear a saída (converter < em <, etc.) e,
no cliente, evitar innerHTML com dados não confiáveis.
Sanear e validar a entrada
Valide tipos, comprimentos e formatos no servidor (nunca confie só na validação do navegador). Rejeite o que não encaixar e normalize o que aceitar.
CORS
O navegador, pela política de mesma origem, bloqueia por padrão que um site em
https://meuapp.com chame por fetch a sua API em https://api.outra.com.
CORS (Cross-Origin Resource Sharing) é o mecanismo pelo qual o seu servidor
autoriza explicitamente quais origens podem chamá-lo, por meio de cabeçalhos
como Access-Control-Allow-Origin. Não é uma proteção contra o atacante: é uma
permissão que a sua API concede a sites de outra origem.
Rate limiting
Limitar quantas requisições um cliente é permitido por unidade de tempo. Freia a força bruta contra o login e os abusos/DoS. Quem passa do limite recebe um 429 Too Many Requests.
Segredos em variáveis de ambiente
As chaves (segredo JWT, senhas de BD, chaves de API) não se escrevem no código nem se sobem ao repositório. Vão em variáveis de ambiente e são lidas em tempo de execução:
const SEGREDO = process.env.JWT_SECRET;
HTTPS sempre
Sem HTTPS, os tokens e as senhas viajam em texto puro e qualquer um na rede pode lê-los. Em produção, todo o tráfego vai cifrado com TLS.
Resumo de defesas
| Risco | Defesa |
|---|---|
| Injeção | Consultas parametrizadas, ORM |
| XSS | Escapar/sanear a saída |
| Roubo de credenciais em trânsito | HTTPS/TLS |
| Força bruta | Rate limiting + hashing lento |
| Segredos vazados | Variáveis de ambiente |
| Chamadas entre origens | CORS configurado de propósito |