A maior parte da segurança de um site vive no código, mas um pequeno conjunto de cabeçalhos de resposta HTTP decide o que o navegador está disposto a fazer com esse código depois que ele chega. São a diferença entre um <script> injetado que executa e um que o navegador recusa executar, entre uma primeira visita em HTTP sem criptografia e uma que já sobe para HTTPS antes de sair da barra de endereços.
E são incomumente baratos de implantar. Cabeçalhos são configuração, não código: a maioria é uma única linha no seu servidor web, CDN ou framework, e se aplicam a todas as respostas de uma vez. Este guia cobre o que cada cabeçalho faz, quais compensam, como implantar uma Content-Security-Policy sem quebrar seu próprio site, e como verificar o que você envia hoje.
Por que os cabeçalhos de segurança importam
Um cabeçalho é uma instrução ao navegador, e o navegador é a única parte capaz de impô-la na máquina do usuário. Isso faz dos cabeçalhos uma segunda linha de defesa que resiste mesmo quando algo antes dela já falhou:
- Eles contêm erros que você já cometeu. Uma Content-Security-Policy não corrige uma falha de XSS, mas pode impedir que o script injetado execute ou que envie algo de volta.
- Eles fecham classes inteiras de ataque. Clickjacking, confusão de tipo MIME e a volta ao HTTP não são bugs do seu código: são comportamentos do navegador dos quais você precisa optar por sair.
- Eles impedem vazamentos silenciosos de dados. Sem uma política de referenciador, a URL completa de uma página privada viaja para cada terceiro de quem você carrega uma imagem.
- São a primeira coisa que um auditor olha. Cabeçalhos ausentes aparecem em toda varredura automática, questionário de segurança e revisão de fornecedor, porque são o achado mais barato que existe.
O problema é que é fácil deixá-los quase certos. Uma CSP com unsafe-inline bloqueia muito pouco; um cabeçalho HSTS com validade de um dia protege quase ninguém. O valor está nos detalhes.
Os cabeçalhos que mais importam
Seis cabeçalhos fazem quase todo o trabalho útil. O resto é legado, de escopo muito estreito, ou foi superado.
| Cabeçalho | O que previne | Esforço |
|---|---|---|
Content-Security-Policy | XSS, exfiltração de dados, código de terceiros inesperado | Alto |
Strict-Transport-Security | Volta ao HTTP, roubo de cookie na primeira requisição | Baixo |
X-Content-Type-Options | Que um arquivo enviado seja executado como script | Trivial |
Referrer-Policy | Vazar URLs completas para terceiros | Trivial |
Permissions-Policy | Acesso a câmera, microfone e localização | Baixo |
Cross-Origin-Opener-Policy | Ataques entre janelas a partir de páginas que você abre | Baixo |
Comece de baixo. Os quatro cabeçalhos baratos são uma linha cada e quase nunca quebram nada, então vale implantá-los hoje; a CSP é a que precisa de um plano.
Content-Security-Policy
A CSP é uma lista de permissões que diz ao navegador de onde cada tipo de recurso pode vir. Uma política razoavelmente rígida fica assim:
default-src 'self'; script-src 'self' 'nonce-r4nd0m'; style-src 'self'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'
Leia diretiva por diretiva. default-src 'self' é o padrão de reserva: tudo o que não for nomeado explicitamente só pode carregar da sua própria origem. script-src é a que mais importa, porque scripts são o que um atacante quer executar. frame-ancestors 'none' diz que nenhum outro site pode colocar sua página em um iframe, e é o substituto moderno de X-Frame-Options. object-src 'none' e base-uri 'self' fecham dois contornos antigos que não custa nada bloquear.
Dois valores decidem se sua política é real. 'unsafe-inline' em script-src permite qualquer <script> inline, incluindo um que o atacante injetou, que é exatamente o que a CSP existe para impedir. 'unsafe-eval' permite eval() e seus parentes. Uma política com qualquer um dos dois ainda vale para as diretivas que não são de script, mas não está protegendo você de XSS.
A saída é um nonce ou um hash. Um nonce é um valor aleatório gerado por resposta e anexado tanto ao cabeçalho quanto a cada <script nonce="..."> legítimo; o navegador executa somente os scripts que carregam esse valor, e um script injetado não consegue adivinhá-lo. Hashes funcionam do mesmo modo para scripts que nunca mudam. Se o seu framework renderiza scripts inline, é quase certo que já suporta nonces; ativar costuma ser uma opção de configuração.
Strict-Transport-Security
O HSTS diz ao navegador para recusar HTTP sem criptografia no seu domínio por um período dado, o que fecha a brecha que só um redirecionamento deixa aberta: a primeiríssima requisição, antes de o redirecionamento chegar, viaja sem criptografia e pode ser interceptada.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
O max-age vem em segundos; um ano é o alvo usual, e menos de alguns meses oferece pouco. includeSubDomains estende a regra a todos os subdomínios, o que a torna eficaz e também o que vale verificar primeiro: qualquer subdomínio ainda servido por HTTP vai parar de funcionar. preload pede inclusão na lista que os navegadores já trazem, de modo que até a primeira visita fique protegida.
Trate o HSTS como difícil de reverter. Um navegador que viu uma política de um ano vai aplicá-la por um ano, não importa o que você envie depois. Implante com um max-age curto, confirme que nada quebrou e só então aumente. E como o HSTS só importa se o certificado por trás for válido, confirme o certificado e seu vencimento com o verificador de certificados SSL antes de assumir uma política longa.
Os cabeçalhos menores
Estes quatro são uma linha cada e raramente polêmicos:
X-Content-Type-Options: nosniff— impede o navegador de adivinhar o tipo de uma resposta pelo conteúdo. Sem ele, um arquivo enviado como.txtpode ser executado como script se o navegador decidir que parece um.Referrer-Policy: strict-origin-when-cross-origin— envia a URL completa à sua própria origem, apenas a origem a outros sites HTTPS, e nada ao cair para HTTP. É o padrão moderno e evita que caminhos e parâmetros privados vazem para terceiros.Permissions-Policy: camera=(), microphone=(), geolocation=()— desliga recursos de dispositivo que seu site não usa, tanto na sua página quanto no que você incorpora.Cross-Origin-Opener-Policy: same-origin— corta a relação de janela com páginas que você abre ou que te abrem, o que bloqueia uma família de ataques entre janelas e é pré-requisito para alguns recursos de isolamento do navegador.
X-Frame-Options: DENY ainda cabe na lista para navegadores antigos, mas frame-ancestors na sua CSP o substitui e é mais expressivo. Envie os dois; eles não entram em conflito.
Como implantar uma CSP com segurança
Uma CSP escrita por adivinhação vai bloquear algo de que seu próprio site precisa. O caminho de «relatar primeiro» evita isso por completo:
- Implante hoje os quatro cabeçalhos baratos.
nosniff, uma política de referenciador, uma política de permissões e HSTS commax-agecurto. Normalmente nenhum deles quebra um site que funciona. - Adicione
Content-Security-Policy-Report-Only. Sintaxe idêntica, mas o navegador apenas relata violações em vez de bloqueá-las. Seu site se comporta exatamente como antes. - Colete relatórios por uma ou duas semanas. Eles vão nomear cada script de terceiros, fonte, endpoint de analytics e manipulador inline que você esqueceu. É o passo que as pessoas pulam, e é o que torna o resto indolor.
- Aperte até os relatórios silenciarem. Adicione as fontes de que realmente precisa e remova as que descobrir que não. Resista a alargar uma diretiva para
*para silenciar um único relatório. - Passe a aplicar. Renomeie o cabeçalho para
Content-Security-Policy. Mantenha a versão somente-relatório ao lado para quando quiser testar uma política mais rígida. - Remova
unsafe-inlinepor último. Este é o trabalho de verdade: mover scripts inline para arquivos ou dar-lhes nonces. Tudo antes disso é preparação; este é o passo que detém o XSS.
Uma nota prática: cabeçalhos são por resposta, então defina-os na borda — seu CDN, proxy reverso ou middleware do framework — e não página por página. Fazer isso em um único lugar também é a única forma de garantir que suas páginas de erro e redirecionamentos também os carreguem, que é justamente onde costumam faltar.
Cabeçalhos que você pode parar de enviar
Alguns conselhos envelheceram mal, e enviar um cabeçalho morto não é inofensivo: adiciona bytes e faz uma auditoria parecer concluída quando não está.
X-XSS-Protection— os filtros do navegador que ele controlava não existem mais. Não faz nada em nenhum navegador atual, e o antigo valormode=blockchegou a introduzir problemas próprios. Remova e confie na CSP.Public-Key-Pins— o HPKP foi removido dos navegadores. Era fácil se trancar fora do próprio domínio, e por isso foi abandonado.Expect-CT— a transparência de certificados já é aplicada por padrão, então o cabeçalho é redundante.Feature-Policy— renomeado paraPermissions-Policy, com sintaxe diferente. Envie o novo; mantenha o antigo só se precisar dar suporte a algo muito velho.
Em contrapartida, uma coisa que vale remover é a informação que você entrega de graça: um cabeçalho Server ou X-Powered-By com a versão exata do seu framework diz ao atacante quais exploits tentar primeiro. Não é uma vulnerabilidade, mas não há razão para publicá-la.
Como verificar seus próprios cabeçalhos
Cabeçalhos são públicos, então verificar a configuração de qualquer site leva segundos:
curl -I https://example.com. Uma requisiçãoHEADimprime todos os cabeçalhos de resposta sem baixar a página. Acrescente-Lpara inspecionar a URL final em vez de um redirecionamento.- O painel de rede do navegador. Abra as ferramentas de desenvolvedor, recarregue, selecione o documento principal e leia a seção de cabeçalhos de resposta. O console também registra cada violação de CSP com a diretiva que bloqueou, que é a forma mais rápida de depurar uma política.
- Um verificador que avalie o resultado. Nosso verificador de cabeçalhos de segurança busca uma URL e informa quais cabeçalhos estão presentes, quais faltam e onde um cabeçalho presente é mais fraco do que parece.
Verifique mais do que a sua home. Cabeçalhos são muitas vezes definidos na aplicação principal, mas não nos hosts de arquivos estáticos, páginas de erro, subdomínios de API ou no redirecionamento que leva de www ao domínio raiz. Já que está aí, confirme que a própria cadeia de redirecionamentos está correta; a referência de códigos de status HTTP cobre qual código cabe em uma mudança permanente.
Para escrever uma política sem decorar a sintaxe, comece pelo nosso gerador de CSP, que também aponta as configurações que a enfraquecem.
Erros comuns a evitar
- Uma CSP com
unsafe-inlineemscript-src. Passa a maioria das verificações automáticas e não detém quase nenhum XSS. Use um nonce ou hashes. - Alargar uma diretiva para
*para resolver um relatório. Adicione a origem específica;*abre mão da diretiva inteira. - HSTS com
max-agelongo no primeiro dia. É, na prática, irreversível pela validade publicada. Comece curto. includeSubDomainsantes de auditar os subdomínios. Tudo que ainda estiver em HTTP, inclusive ferramentas internas, para de carregar.- Cabeçalhos na aplicação, mas não na borda. Páginas de erro, redirecionamentos e hosts de arquivos ficam desprotegidos, e são justamente as respostas que os atacantes buscam.
- Definir o mesmo cabeçalho duas vezes. Dois cabeçalhos CSP são intersectados, não mesclados, então o resultado é mais rígido que qualquer um e costuma quebrar algo; dois valores conflitantes de
X-Frame-Optionspodem ser ignorados por completo. - Continuar enviando
X-XSS-Protectione considerar feito. Um cabeçalho morto dá falso conforto em um relatório. - Nunca sair do modo somente-relatório. Relatórios sobre os quais você não age não protegem ninguém.
Verifique seus cabeçalhos
Cabeçalhos de segurança oferecem a melhor relação entre proteção e esforço disponível na web: quatro deles são uma única linha cada, e o quinto, a CSP, é sobretudo uma questão de ouvir seus próprios relatórios de violação antes de aplicar qualquer coisa. Comece olhando o que seu site envia hoje, adicione os cabeçalhos baratos imediatamente, e então coloque uma CSP em modo somente-relatório e deixe que ela diga o que sua política precisa dizer.
Ferramentas e guias relacionados:
- Verificador de cabeçalhos de segurança — veja quais cabeçalhos uma URL envia e quais faltam.
- Verificador de certificados SSL — confira o certificado por trás da sua política HSTS.
- Códigos de status HTTP — garanta que seu redirecionamento HTTPS devolve o código certo.
- Consulta DNS: guia completo — os registros por trás de cada nome de host da sua política.
Perguntas frequentes
Quais cabeçalhos de segurança devo adicionar primeiro?⌄
Comece pelos quatro que quase nunca quebram nada: X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, uma Permissions-Policy desligando recursos de dispositivo que você não usa, e Strict-Transport-Security com um max-age curto que você aumenta depois. Então adicione uma Content-Security-Policy em modo somente-relatório, porque é a que precisa de observação antes da aplicação.
Uma CSP com unsafe-inline ainda ajuda?⌄
Ajuda em tudo, exceto no ataque que a CSP detém melhor. Diretivas como img-src, connect-src, frame-ancestors e object-src continuam limitando para onde os dados podem ir e quem pode te enquadrar. Mas 'unsafe-inline' em script-src permite que qualquer script inline injetado execute, então a política não está protegendo você de XSS. Substitua por um nonce por resposta ou por hashes de script.
Strict-Transport-Security é arriscado?⌄
É arriscado principalmente porque é difícil desfazer: um navegador que viu max-age=31536000 vai recusar HTTP sem criptografia no seu domínio por um ano, independentemente do que você enviar depois. Implante primeiro com um max-age curto, confirme que todos os subdomínios estão acessíveis por HTTPS antes de adicionar includeSubDomains, e só então aumente a validade e considere preload.
O que substituiu X-Frame-Options e X-XSS-Protection?⌄
A diretiva frame-ancestors da Content-Security-Policy substitui X-Frame-Options e é mais expressiva, embora enviar as duas seja inofensivo e ainda ajude navegadores antigos. X-XSS-Protection não tem substituto porque os filtros do navegador que ele controlava foram removidos; a CSP é o que detém XSS agora, e o cabeçalho antigo pode simplesmente ser removido.
Onde devo definir os cabeçalhos de segurança?⌄
Na borda, em um só lugar: seu CDN, proxy reverso ou middleware do framework. Definir por página deixa suas páginas de erro, redirecionamentos, hosts de arquivos e respostas de API sem cobertura, e são exatamente as respostas que passam batido em uma auditoria e são buscadas em um ataque.
Como verifico quais cabeçalhos meu site envia?⌄
Rode curl -I https://seudominio.com acrescentando -L para ver o destino final em vez de um redirecionamento, ou abra o painel de rede do navegador e leia os cabeçalhos de resposta do documento principal. O verificador de cabeçalhos de segurança faz isso a partir do seu navegador e sinaliza tanto os cabeçalhos ausentes quanto os presentes que são mais fracos do que parecem.
Mais de 15 anos de experiência prática em desenvolvimento web e segurança. Foco em segurança web prática: manter sites seguros, confiáveis e fáceis de diagnosticar. O BuildToolForge existe para tornar essas verificações gratuitas, privadas e compreensíveis. As ferramentas rodam no seu navegador sempre que possível, e nada do que você digita em uma ferramenta é armazenado.
Como escrevemos nossos guias: Cada guia nasce da experiência prática, é conferido com os padrões oficiais e testado com nossas próprias ferramentas em domínios reais. Atualizamos os guias quando padrões ou ferramentas mudam. Encontrou um erro? Escreva para contact@buildtoolforge.com.