Cabeçalhos HTTP de segurança: CSP, HSTS e os outros
Quais cabeçalhos HTTP de segurança configurar, com valores de partida, o que cada um quebra se errar e como implantar a CSP sem derrubar o site.
Nesta página 11 min de leitura
- Resumo: valores de partida e o que pode quebrar
- Strict-Transport-Security (HSTS)
- Content-Security-Policy (CSP)
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
- X-Frame-Options ou frame-ancestors
- Cross-Origin-Opener-Policy e Cross-Origin-Resource-Policy
- Cabeçalhos que não devem mais ser usados
- Um conjunto inicial completo
- Como verificar o seu site
Os cabeçalhos HTTP de segurança que valem para quase todo site são: Strict-Transport-Security (força HTTPS), Content-Security-Policy (limita scripts e quem pode exibir a página num iframe), X-Content-Type-Options: nosniff, Referrer-Policy e Permissions-Policy. X-Frame-Options ainda serve como reserva para navegadores antigos, e Cross-Origin-Opener-Policy e Cross-Origin-Resource-Policy isolam a página de outros sites. X-XSS-Protection, Expect-CT e Feature-Policy não devem mais ser usados. A CSP é o que dá mais trabalho e o que mais quebra; ela deve entrar primeiro em modo de relatório.
Este texto cobre o comportamento dos navegadores e as recomendações da MDN, da OWASP e do W3C em outubro de 2026. Ele faz parte do guia de segurança básica de um site, que trata de HTTPS, arquivos expostos, versões e cookies.
Resumo: valores de partida e o que pode quebrar
Os valores abaixo são um ponto de partida comum, baseado nas referências citadas em cada seção. Não são os únicos corretos: cada site precisa ajustar conforme o que usa.
| Cabeçalho | Valor de partida | O que pode quebrar |
|---|---|---|
Strict-Transport-Security | max-age=63072000; includeSubDomains | Subdomínios que ainda não têm HTTPS ficam inacessíveis |
Content-Security-Policy | Política com nonce, object-src 'none', base-uri 'none' e frame-ancestors | Scripts inline, eventos onclick, eval(), widgets de terceiros |
X-Content-Type-Options | nosniff | Scripts e CSS servidos com Content-Type errado |
Referrer-Policy | strict-origin-when-cross-origin | Ferramentas que dependem do caminho completo de origem em outro domínio |
Permissions-Policy | camera=(), microphone=(), geolocation=() | Recursos que o site ou um iframe de parceiro usa de fato |
X-Frame-Options | DENY ou SAMEORIGIN | Exibição legítima do site dentro de iframes |
Cross-Origin-Opener-Policy | same-origin, ou same-origin-allow-popups se houver login ou pagamento em pop-up | Pop-ups de OAuth e pagamento que conversam com a janela que os abriu |
Cross-Origin-Resource-Policy | same-site | Arquivos do seu domínio usados por outros sites |
Strict-Transport-Security (HSTS)
O HSTS diz ao navegador que aquele host só pode ser acessado em HTTPS durante max-age segundos. Depois de receber o cabeçalho, o navegador converte sozinho os pedidos http em https e não deixa o usuário ignorar erros de certificado (MDN: Strict-Transport-Security). Três detalhes importam:
O cabeçalho só vale se vier numa resposta HTTPS; enviado em http, é ignorado.
Ele só protege a partir da segunda visita, porque o navegador precisa ter recebido o cabeçalho uma vez. A lista de pré-carregamento dos navegadores (
preload) fecha essa brecha.includeSubDomainsestende a regra a todos os subdomínios, presentes e futuros.
Strict-Transport-Security: max-age=63072000; includeSubDomainsA Mozilla recomenda no mínimo seis meses e sugere dois anos (63072000) (MDN: guia prático de TLS); o ASVS 5.0 pede no mínimo um ano e, a partir do nível 2, a inclusão dos subdomínios (ASVS 5.0, requisito 3.4.1). Recomendação de implantação: comece com um max-age curto, confira que tudo funciona e só então aumente, porque o navegador vai lembrar da regra pelo prazo inteiro. A OWASP alerta que um HSTS mal configurado ou um problema de certificado pode deixar usuários sem acesso durante todo o max-age (OWASP HTTP Headers Cheat Sheet).
Para entrar na lista de pré-carregamento, o site precisa de certificado válido, redirecionar http para https no mesmo host, ter HTTPS em todos os subdomínios e enviar max-age de pelo menos um ano com includeSubDomains e preload. A saída da lista é lenta (pode levar meses para chegar aos usuários) e outros navegadores não têm obrigação de acompanhar a remoção (hstspreload.org). Só faça o pedido se todos os subdomínios, inclusive os internos, vão ficar em HTTPS a longo prazo.
Content-Security-Policy (CSP)
A CSP é uma lista de regras que diz ao navegador de onde a página pode carregar scripts, estilos, imagens, iframes e para onde pode enviar dados. Seu uso principal é reduzir o efeito de XSS (cross-site scripting, a injeção de script na página): mesmo que um atacante consiga inserir um <script>, o navegador não o executa se ele não cumprir a política. Ela é uma camada a mais e não substitui a correção das falhas de XSS (web.dev: strict CSP).
Lista de domínios ou política estrita com nonce
Há dois jeitos de escrever a regra de scripts. O antigo é listar domínios permitidos (script-src 'self' https://cdn.exemplo.com). O recomendado pela MDN e pelo web.dev é a chamada CSP estrita, baseada em nonce ou hash (MDN: guia de CSP; web.dev: strict CSP). O ASVS 5.0 aceita as duas formas no nível 2, desde que a política tenha object-src 'none' e base-uri 'none', e exige nonce ou hash por resposta no nível 3 (ASVS 5.0, requisito 3.4.3).
Um nonce é um valor aleatório que o servidor gera a cada resposta, coloca no cabeçalho e repete no atributo nonce de cada <script> legítimo. O navegador só executa os scripts que trazem o valor certo. O nonce precisa ser imprevisível e diferente em cada resposta, e deve ser inserido pelo sistema de templates, nunca em todos os <script> da página de forma indiscriminada, para não carimbar também um script injetado (MDN: guia de CSP).
Content-Security-Policy:
script-src 'nonce-R4nd0mPorResposta' 'strict-dynamic';
object-src 'none';
base-uri 'none';
frame-ancestors 'self'
<script nonce="R4nd0mPorResposta" src="/js/app.js"></script>'strict-dynamic' faz com que scripts criados por um script já confiável também rodem. Isso permite que bibliotecas e widgets de terceiros carreguem seus próprios arquivos sem que você liste cada domínio (web.dev: strict CSP). Para páginas estáticas ou servidas de cache, o web.dev recomenda hash no lugar de nonce: 'sha256-...' calculado sobre o conteúdo de cada script inline. Um nonce gravado numa página em cache se repete para todos os visitantes e perde o sentido.
frame-ancestors
A diretiva frame-ancestors define quais páginas podem exibir o site dentro de um <iframe>, o que protege contra clickjacking (quando outro site mostra o seu por baixo de botões falsos). A MDN recomenda 'none' para sites que não precisam ser incorporados (MDN: guia de CSP). Ela não herda o valor de default-src e não funciona em meta tag (MDN: frame-ancestors).
Content-Security-Policy: frame-ancestors 'none'
Content-Security-Policy: frame-ancestors 'self' https://parceiro.exemplo.comModo somente relatório
O cabeçalho Content-Security-Policy-Report-Only aplica a mesma sintaxe sem bloquear nada: o navegador só registra e envia as violações (MDN: Content-Security-Policy-Report-Only). Os dois cabeçalhos podem ser enviados juntos; nesse caso a política normal é aplicada e a de relatório só gera avisos, o que permite testar uma versão mais rígida sem mexer na que está valendo (MDN: guia de CSP).
Os relatórios vão para o endereço definido no cabeçalho Reporting-Endpoints e referenciado pela diretiva report-to. A diretiva antiga report-uri está obsoleta, mas a MDN recomenda declarar as duas enquanto report-to não funcionar em todos os navegadores (MDN: guia de CSP; W3C: CSP Level 3).
Reporting-Endpoints: csp="https://exemplo.com.br/csp-relatorios"
Content-Security-Policy-Report-Only:
script-src 'nonce-R4nd0mPorResposta' 'strict-dynamic';
object-src 'none';
base-uri 'none';
report-uri https://exemplo.com.br/csp-relatorios;
report-to cspComo implantar a CSP sem derrubar o site
Liste os scripts e recursos de cada tipo de página (home, produto, checkout, área logada) pela aba Network do DevTools.
Escolha nonce, se as páginas são geradas no servidor a cada requisição, ou hash, se são estáticas ou ficam em cache (web.dev).
Ajuste o código que a política vai bloquear: troque eventos inline como
onclickporaddEventListener, troque linksjavascript:por eventos e substituaeval()(por exemplo, porJSON.parse()) (web.dev).Publique a política em
Content-Security-Policy-Report-Onlycom um endpoint de relatórios.Acompanhe os relatórios por tempo suficiente para cobrir todos os tipos de página e fluxos, incluindo checkout e campanhas sazonais, e corrija ou libere cada origem legítima.
Troque para
Content-Security-Policye mantenha o envio de relatórios.Revise a política no CSP Evaluator ou no Lighthouse antes e depois da troca, como sugere o web.dev.
O que costuma quebrar
Scripts inline sem nonce ou hash, inclusive os que plugins e temas imprimem na página.
Atributos de evento (
onclick,onload) e linksjavascript:, que a CSP estrita bloqueia.Bibliotecas que usam
eval()ounew Function(). Liberar com'unsafe-eval'enfraquece a política (web.dev).Nonce em página guardada em cache, que repete o valor e faz scripts falharem ou deixa a proteção sem efeito.
Com política de lista de domínios: qualquer origem nova (um pixel, um chat, uma fonte) fica bloqueada até alguém atualizar a lista.
X-Content-Type-Options
Com nosniff, o navegador para de adivinhar o tipo do arquivo pelo conteúdo e usa o Content-Type declarado. Requisições de script são bloqueadas se o tipo não for de JavaScript, e de folha de estilo se não for text/css. Isso evita, por exemplo, que um arquivo enviado por usuário como texto seja executado como HTML ou script (MDN: X-Content-Type-Options). O ASVS pede o cabeçalho em todas as respostas (requisito 3.4.4).
X-Content-Type-Options: nosniffO que quebra: arquivos servidos com tipo errado, como um .js entregue como text/plain. Antes de ativar, confira o Content-Type dos seus scripts e CSS, principalmente os gerados dinamicamente.
Referrer-Policy
O cabeçalho Referer conta ao site de destino de onde o visitante veio. Se o endereço tiver dados no caminho ou na query string (um token, um e-mail, um número de pedido), eles vazam para terceiros. A Referrer-Policy controla quanto desse endereço é enviado. Quando o site não define nada, o padrão dos navegadores hoje é strict-origin-when-cross-origin: o endereço completo para o próprio site, só a origem para outros sites em HTTPS e nada quando a conexão cai para HTTP (MDN: Referrer-Policy).
Referrer-Policy: strict-origin-when-cross-originA OWASP recomenda declarar o cabeçalho em vez de depender do padrão do navegador e usa esse valor como exemplo (OWASP HTTP Headers Cheat Sheet); a lista de valores do OWASP Secure Headers Project vai além e sugere no-referrer (headers_add.json). no-referrer é mais restritivo, mas pode atrapalhar ferramentas de análise que dependem da origem do tráfego. Evite unsafe-url, que envia o endereço completo até para destinos em HTTP.
Permissions-Policy
A Permissions-Policy liga ou desliga recursos do navegador, como câmera, microfone, geolocalização e pagamento, para a página e para os iframes dentro dela. () desliga o recurso em todo lugar; self libera só para a mesma origem; uma origem entre aspas libera para aquele domínio (MDN: Permissions-Policy).
Permissions-Policy: camera=(), microphone=(), geolocation=()
Permissions-Policy: geolocation=(self "https://mapas.exemplo.com"), microphone=()A recomendação da OWASP é desligar tudo o que o site não usa (OWASP HTTP Headers Cheat Sheet). A MDN marca o cabeçalho como experimental e diz que ele não funciona em alguns navegadores muito usados, então trate-o como proteção adicional, não como a única barreira. O que quebra: um iframe de parceiro (mapa, vídeo, pagamento) que precisa de um recurso desligado. No iframe, o atributo allow concede o recurso dentro do limite que o cabeçalho permite.
X-Frame-Options ou frame-ancestors
X-Frame-Options foi o primeiro cabeçalho contra clickjacking. Aceita DENY (ninguém exibe a página em iframe) e SAMEORIGIN (só páginas da mesma origem). O valor ALLOW-FROM é obsoleto e faz navegadores modernos ignorarem o cabeçalho inteiro, e o cabeçalho não tem efeito em meta tag (MDN: X-Frame-Options).
A diretiva frame-ancestors da CSP faz o mesmo com mais opções, como liberar domínios específicos. A especificação da CSP define que, quando há uma política com frame-ancestors sendo aplicada, o navegador ignora o X-Frame-Options (W3C: CSP Level 3, seção 6.4.2.2). O ASVS 5.0 trata o X-Frame-Options como obsoleto e pede frame-ancestors (requisito 3.4.6). Recomendação: use frame-ancestors como regra principal e mantenha um X-Frame-Options coerente para navegadores antigos. Ele não atrapalha os novos, que já o ignoram nesse caso.
Cross-Origin-Opener-Policy e Cross-Origin-Resource-Policy
O Cross-Origin-Opener-Policy (COOP) decide se a sua página compartilha o contexto de navegação com janelas de outros sites que ela abriu ou que a abriram. Com same-origin, uma janela de outro domínio fica isolada e perde a referência window.opener. Isso quebra fluxos de login (OAuth) e de pagamento em pop-up que devolvem o resultado para a janela original; para esses casos existe same-origin-allow-popups (MDN: Cross-Origin-Opener-Policy). O ASVS pede um dos dois valores nas respostas que abrem documentos (requisito 3.4.8).
Cross-Origin-Opener-Policy: same-origin-allow-popupsO Cross-Origin-Resource-Policy (CORP) vai no recurso, não na página. Ele diz quais origens podem carregar aquele arquivo em requisições sem CORS, como <img> e <script>: same-origin, same-site ou cross-origin (MDN: Cross-Origin-Resource-Policy). A Mozilla lista o CORP entre as proteções contra ataques de canal lateral especulativo (MDN: guias práticos), e a OWASP sugere same-site. O que quebra: imagens, fontes ou scripts do seu domínio usados por outros sites, como um widget que você distribui. Esses arquivos precisam de cross-origin.
O par Cross-Origin-Embedder-Policy: require-corp com COOP same-origin ativa o isolamento entre origens, necessário para recursos como SharedArrayBuffer (MDN). O COEP bloqueia recursos de outras origens que não autorizem o uso por CORP ou CORS (OWASP). Opinião: num site institucional ou loja que não precisa desse isolamento, o COEP costuma custar mais (anúncios, vídeos e widgets bloqueados) do que entrega.
Cabeçalhos que não devem mais ser usados
| Cabeçalho | Situação | O que fazer |
|---|---|---|
X-XSS-Protection | Fora de qualquer especificação e obsoleto. A MDN avisa que o filtro pode criar falhas de XSS em sites que não as tinham (MDN) | Não enviar, ou enviar 0 para desligar o filtro, como sugere a OWASP; proteger com CSP |
Expect-CT | Só o Chromium implementou, e ele o considera obsoleto desde a versão 107, porque já exige Certificate Transparency por padrão (MDN) | Remover |
Feature-Policy | Renomeado para Permissions-Policy, com outra sintaxe. No Chrome funciona só como apelido, e a Permissions-Policy prevalece quando os dois vêm juntos (Chrome for Developers) | Migrar para Permissions-Policy |
Public-Key-Pins | A OWASP recomenda não usar e remover de produção (OWASP) | Remover |
Um conjunto inicial completo
Um exemplo para um site servido dinamicamente, sem incorporação por outros sites e com pagamento em pop-up. A forma de configurar depende do servidor (nginx, Apache), do CDN ou do framework; o conteúdo dos cabeçalhos é o mesmo.
Strict-Transport-Security: max-age=63072000; includeSubDomains
Content-Security-Policy: script-src 'nonce-{gerado por resposta}' 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; report-to csp
Reporting-Endpoints: csp="https://exemplo.com.br/csp-relatorios"
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-Frame-Options: DENY
Cross-Origin-Opener-Policy: same-origin-allow-popupsPara comparar, o OWASP Secure Headers Project publica uma lista mais rígida e atualizada com frequência, pensada como referência máxima e não como configuração para copiar sem testar (headers_add.json).
Como verificar o seu site
No terminal, curl -sI https://exemplo.com.br/ mostra os cabeçalhos de uma resposta. Repita para uma página interna, um arquivo de imagem e uma resposta de erro, porque servidores e CDNs nem sempre aplicam os mesmos cabeçalhos em tudo. O HTTP Observatory da Mozilla dá uma nota e explica cada item. A auditoria do WebVyze aponta a falta de HSTS, CSP, X-Content-Type-Options e Referrer-Policy, a CSP que existe mas não barra scripts injetados e a página que pode ser embutida por outros sites, cada uma com o guia de correção. Em lojas, a CSP da página de pagamento também conta para o PCI DSS; o artigo sobre os requisitos 6.4.3 e 11.6.1 explica como, e os planos pagos do WebVyze mantêm um inventário dos scripts das páginas de checkout. O WebVyze só lê páginas públicas e não altera nada no site.
Perguntas frequentes
- Posso colocar a CSP numa meta tag em vez de no cabeçalho?
- Pode, com limites. A especificação ignora as diretivas frame-ancestors, report-uri e sandbox quando a política vem de uma meta tag, e o modo somente relatório (Content-Security-Policy-Report-Only) não funciona em meta tag. Para uma política completa, use o cabeçalho.
- Os cabeçalhos precisam estar em todas as respostas ou só nas páginas HTML?
- Depende do cabeçalho. O ASVS 5.0 pede HSTS, nosniff e frame-ancestors em todas as respostas e o Cross-Origin-Opener-Policy nas respostas que abrem um documento, como as páginas HTML. Configurar no servidor ou no CDN para todas as respostas costuma ser o caminho mais simples.
- Remover os cabeçalhos Server e X-Powered-By melhora a segurança?
- Dificulta a identificação da tecnologia usada, e a OWASP recomenda remover ou deixar esses cabeçalhos sem informação útil. Não impede que alguém descubra a tecnologia por outros meios e não dispensa as atualizações.
- Como receber os relatórios de violação da CSP?
- O navegador envia um POST em JSON para o endereço declarado em Reporting-Endpoints (diretiva report-to) ou em report-uri. Você precisa de um endpoint que aceite e guarde esses envios: um serviço próprio simples ou uma ferramenta de terceiros.
Veja o que o seu site precisa corrigir.
Checagem grátis por lei, com a causa e o guia de correção de cada problema.
Continue lendo
- SEO técnico
Robôs de IA no robots.txt: busca, acesso do usuário e treinamento
GPTBot, ClaudeBot, OAI-SearchBot, Google-Extended: o que cada robô de IA faz, se respeita o robots.txt e como bloquear o treinamento sem sair da busca.
- SEO técnico
Redirecionamentos: cadeias, loops e como corrigir
Como o Google trata 301, 302, 307 e 308, o que cadeias e loops causam no rastreamento e na velocidade, e como mapear, corrigir e testar redirecionamentos.
- SEO técnico
llms.txt: o que é, o que não faz e como criar
O llms.txt resume o site para agentes de IA. Veja o formato, o que Google e outras empresas dizem sobre ele, quando vale criar e como escrever um bom arquivo.