Uma landing page criada por IA pode funcionar no preview e falhar assim que o formulário chama uma API em outro domínio. O console mostra um erro de CORS, alguém adiciona * no servidor e a requisição passa — mas a política pode ter ficado mais ampla do que a integração exige.
Validar CORS é reproduzir a troca que o navegador realmente faz: origem exata, método, headers, preflight, credenciais e resposta. Também é reconhecer o limite do mecanismo. CORS controla se o JavaScript de uma origem pode ler determinada resposta; não autentica a pessoa, não impede chamadas fora do navegador e não substitui autorização no backend.
Este guia organiza o teste entre a página publicada e o serviço que recebe a requisição.
Identifique as duas origens
Uma origem combina scheme, host e porta. Estes endereços têm origens diferentes:
https://campanha.exemplo.comhttps://api.exemplo.comhttps://campanha.exemplo.com:8443http://campanha.exemplo.comCaminhos não mudam a origem. Portas e protocolo mudam.
Registre o fluxo antes de editar headers:
origem da landing publicada:origens de preview realmente usadas:endpoint da API:método:headers enviados:content type:credenciais incluídas:resposta que o JavaScript precisa ler:responsável pelo servidor:Se o Site usa o endereço padrão e um domínio próprio, não coloque os dois na allowlist por reflexo. Autorize apenas os hostnames que realmente executam a integração e teste cada um separadamente.
Entenda quem configura CORS
CORS é expresso por headers na resposta do servidor que recebe a chamada. A documentação da MDN descreve o mecanismo que permite ao servidor indicar quais origens podem ler recursos e como o navegador faz uma requisição de preflight antes de certas chamadas.
Isso define uma divisão clara:
- o frontend escolhe URL, método, headers e política de credenciais;
- o navegador envia
Origine, quando necessário,OPTIONS; - o servidor da API decide quais origens, métodos e headers aceita;
- o navegador libera ou bloqueia a resposta para o JavaScript.
Adicionar mode: "no-cors" não corrige a API. Esse modo produz uma resposta opaca que o JavaScript não consegue ler e restringe o que pode ser enviado. Corrija o contrato no servidor responsável.
O Site no Ar publica o pacote estático da landing page. A documentação de Publicação não cria uma API de formulário nem configura CORS no serviço externo. O proprietário do endpoint precisa participar da correção.
Descubra se haverá preflight
Algumas requisições consideradas simples podem seguir diretamente. Outras exigem que o navegador envie OPTIONS antes da chamada real.
Um POST com JSON normalmente provoca preflight porque application/json não é um dos content types simples. Um header Authorization ou um header personalizado também costuma provocar essa etapa.
No preflight, o navegador informa a origem, o método pretendido e os nomes dos headers:
OPTIONS /leads HTTP/1.1Origin: https://campanha.exemplo.comAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: content-typeUma resposta compatível pode declarar:
HTTP/1.1 204 No ContentAccess-Control-Allow-Origin: https://campanha.exemplo.comAccess-Control-Allow-Methods: POSTAccess-Control-Allow-Headers: Content-TypeVary: OriginO preflight não envia o corpo do formulário. Ele verifica se a chamada planejada é permitida. A resposta real ainda precisa trazer os headers CORS adequados.
Reproduza a troca com a origem exata
Teste o preflight sem credenciais reais e com o mesmo método e headers da página:
curl -sS -D - -o /dev/null -X OPTIONS \ -H 'Origin: https://campanha.exemplo.com' \ -H 'Access-Control-Request-Method: POST' \ -H 'Access-Control-Request-Headers: content-type' \ https://api.exemplo.com/leadsDepois confira:
- status retornado pelo
OPTIONS; Access-Control-Allow-Originigual à origem testada;- método presente em
Access-Control-Allow-Methods; - headers necessários em
Access-Control-Allow-Headers; - política aplicada também a respostas de erro;
Vary: Originquando a resposta varia por origem e passa por cache.
Um curl sem Origin não reproduz a requisição do navegador. Um teste feito apenas com a origem local também não prova que o domínio publicado está autorizado.
Use credenciais somente quando o contrato exige
Por padrão, fetch() cross-origin não inclui cookies. Quando a integração realmente depende de sessão, o frontend pode pedir credentials: "include", mas o servidor precisa responder de forma compatível.
Para uma chamada com credenciais:
Access-Control-Allow-Originprecisa trazer uma origem explícita, não*;Access-Control-Allow-Credentials: trueprecisa estar presente;- cookies continuam sujeitos a atributos como
SameSiteeSecure; - autenticação e autorização precisam ser verificadas no servidor;
- a proteção contra CSRF continua sendo uma decisão separada.
A MDN destaca que wildcards não são válidos para os campos CORS relevantes de respostas com credenciais. Trocar uma origem explícita por * para eliminar um erro cria um contrato diferente e ainda falha no navegador quando cookies estão envolvidos.
Se a landing envia um lead a um endpoint público sem sessão, não habilite credenciais por hábito. Defina proteção contra abuso, validação e limites no backend de acordo com o caso.
Não reflita qualquer Origin
Alguns servidores copiam o valor recebido em Origin para Access-Control-Allow-Origin. Esse padrão só é seguro quando o valor foi comparado com uma allowlist controlada.
Evite:
- refletir qualquer origem;
- aceitar sufixos com comparação textual ingênua;
- confiar em
nullsem um caso documentado; - liberar todos os métodos e headers;
- permitir origens de preview antigas indefinidamente;
- manter
localhostna configuração de produção.
Normalize e compare origens completas. https://campanha.exemplo.com.atacante.test não pertence a exemplo.com, apesar de conter o texto esperado.
Quando houver múltiplos domínios autorizados, devolva a origem exata que passou na allowlist e inclua Vary: Origin para caches não reutilizarem a resposta entre origens diferentes.
Teste sucesso, erro e redirecionamento
Uma integração pode passar no caminho feliz e falhar quando mais importa. Verifique:
| Cenário | Evidência esperada |
|---|---|
| preflight permitido | OPTIONS aceita origem, método e headers |
| origem não autorizada | navegador não libera a resposta |
| validação inválida | resposta 4xx continua com CORS para o frontend ler |
| erro do serviço | resposta não expõe detalhes internos |
| rate limit | frontend reconhece o status sem confirmação falsa |
| redirecionamento | destino final mantém contrato compatível |
| domínio próprio | origem final funciona sem depender do preview |
| credencial ausente | backend rejeita conforme o contrato, não por acaso CORS |
Headers adicionados apenas a respostas 2xx deixam o formulário sem acesso ao corpo de erro. A pessoa vê uma mensagem genérica de rede quando a API tentou devolver uma validação útil.
Use o navegador como prova funcional
O curl inspeciona a conversa HTTP, mas não aplica todas as decisões do navegador. Na URL publicada:
- abra DevTools em uma sessão limpa;
- envie apenas dados sintéticos autorizados;
- localize
OPTIONSe a requisição real no painel Network; - confira
Origin, método, request headers e response headers; - confirme que o JavaScript consegue ler sucesso e erro;
- repita no endereço padrão e no domínio próprio que permanecerão ativos;
- teste uma origem não autorizada;
- registre URL, commit, endpoint e resultado.
O guia de testes de formulário amplia a verificação para validação, consentimento, estados e confirmação no sistema receptor.
CORS não protege o endpoint sozinho
Uma chamada bloqueada pelo navegador ainda pode ser feita por servidor, script ou cliente HTTP. O backend precisa validar entrada, autenticar quando necessário, autorizar operações e limitar abuso independentemente de CORS.
Também não envie chave privada no JavaScript para “proteger” um endpoint público. Qualquer pessoa pode inspecionar o bundle e as requisições. O guia para evitar chaves no frontend explica como separar configuração pública de credenciais privadas.
Para scripts ou stylesheets externos usados com SRI, valide CORS com a origem real da página. O artigo de Subresource Integrity detalha esse caso, em que a resposta da CDN precisa permitir a verificação cross-origin.
Prompt copiável para o agente
Valide o contrato CORS desta landing page sem ampliar permissões.
Origem publicada: [scheme + host + porta]Origens adicionais autorizadas: [lista]Endpoint: [URL]Método: [método]Headers enviados: [lista]Credenciais: [omit ou include]
- Mostre se a chamada exige preflight.- Reproduza OPTIONS com Origin, método e headers exatos.- Confira respostas de sucesso, validação e erro.- Não use wildcard com credenciais.- Não reflita Origin sem allowlist.- Não adicione mode no-cors como correção.- Diferencie erro CORS, autenticação, autorização e falha de rede.- Teste no navegador a URL publicada e uma origem rejeitada.- Devolva headers observados, mudança proposta e evidências.Checklist final
- origem da página registrada com scheme, host e porta;
- endpoint, método e headers inventariados;
- necessidade de preflight confirmada;
-
OPTIONStestado comOriginreal; - allow-origin usa o menor escopo necessário;
- métodos e headers permitidos são explícitos;
- credenciais só estão ativas quando exigidas;
- respostas 2xx, 4xx e 5xx foram verificadas;
- cache varia por origem quando necessário;
- origem não autorizada foi rejeitada;
- autenticação, autorização e CSRF foram tratados separadamente;
- URL publicada passou no navegador com dados sintéticos.
CORS deixa de ser uma tentativa de apagar erros do console quando cada lado do contrato está explícito. A landing sabe o que envia, a API sabe qual origem aceita e o navegador confirma que aquela resposta pode ser entregue ao código certo — sem abrir acesso além do necessário.
