Skip to content
IsSafeSite
2 min de leituraIsSafeSite Team

CORS explicado: configuração de origem cruzada segura para sites modernos

CORS é tão mal compreendido quanto mal configurado. Veja o que os cabeçalhos realmente fazem, a armadilha do curinga com credenciais e como trancar uma API corretamente.

CORSAPIsEndurecimento

O compartilhamento de recursos entre origens (CORS) é onde muitas equipes conhecem a segurança do navegador pela primeira vez — geralmente porque algo quebrou e o resultado de busca mais rápido dizia para "apenas permitir todas as origens". Essa correção funciona e, em silêncio, vira uma vulnerabilidade. Veja o que o CORS realmente faz e como configurá-lo sem abrir sua API para todos os sites da internet.

O que o CORS realmente controla

CORS não é um controle de acesso do lado do servidor. É um mecanismo do navegador que decide se o JavaScript rodando na origem A pode *ler* uma resposta da origem B. Ele não faz nada para deter uma requisição direta do curl, de um servidor ou de um script que ignora o navegador. Trate-o como uma proteção para clientes de navegador e mantenha a autorização de verdade no servidor de qualquer forma.

A armadilha do curinga com credenciais

A configuração de CORS mais perigosa é refletir a origem da requisição enquanto também permite credenciais:

Access-Control-Allow-Origin: https://evil.example
Access-Control-Allow-Credentials: true

Se o seu servidor devolve qualquer Origin que recebe e define Allow-Credentials: true, qualquer site pode fazer requisições autenticadas como o seu usuário logado e ler a resposta. O navegador proíbe o * literal junto com credenciais por isso — mas refletir a origem contorna essa proteção e recria o buraco.

Uma configuração correta e restritiva

Compare a origem recebida com uma lista de permissões explícita e só então a devolva:

const allowed = new Set([
  'https://app.example.com',
  'https://admin.example.com',
]);

const origin = req.headers.get('origin');
if (origin && allowed.has(origin)) {
  res.setHeader('Access-Control-Allow-Origin', origin);
  res.setHeader('Vary', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
}

O cabeçalho Vary: Origin é fácil de esquecer e importante: sem ele, um cache pode servir o cabeçalho de permissão de uma origem a outra diferente.

Restrinja também métodos e cabeçalhos

Access-Control-Allow-Origin é apenas metade da política. Mantenha o resto apertado:

  • Permita apenas os métodos que o endpoint usa, por ex. Access-Control-Allow-Methods: GET, POST.
  • Permita apenas os cabeçalhos de requisição que você espera, não uma lista genérica.
  • Defina um Access-Control-Max-Age razoável para que os preflights sejam cacheados.
  • Nunca combine Allow-Origin: * com Allow-Credentials: true.

Quando um curinga realmente serve

Uma API verdadeiramente pública, sem autenticação e somente leitura — um feed de câmbio, um endpoint de status público — pode usar Access-Control-Allow-Origin: * com segurança, justamente porque não há credenciais nem nada privado para vazar. O perigo é sempre apenas a abertura tipo * combinada com autenticação.

Teste a partir de um contexto de origem cruzada real

O CORS se comporta de forma diferente para requisições simples e para as com preflight, então teste ambas a partir de um navegador em outra origem, não apenas com curl (que ignora o CORS por completo). Uma análise verifica seus cabeçalhos de resposta CORS automaticamente junto com o resto das suas verificações de segurança; para ver como as constatações de CORS entram em uma lista priorizada de correções, leia Como ler um relatório de análise de segurança de site.

Transforme essas verificações em um relatório de análise do seu próprio site.

Rode uma análise gratuita e receba constatações priorizadas e acionáveis em cerca de 30 segundos.

Analisar meu site

Continue lendo