VERIFICAÇÃO CABEÇALHO POR CABEÇALHO

Cabeçalhos de segurança HTTP: como verificar e corrigir os que faltam no seu site

Cabeçalhos de segurança são instruções que o servidor envia junto com as respostas: de onde a página pode carregar recursos, se o navegador deve insistir no HTTPS, quem pode exibir a página dentro de um frame. Veja como lê-los você mesmo, o que cada um faz, valores iniciais seguros e uma ordem de implantação que permite testar cada mudança antes de aplicá-la de vez.

Ilustração conceitual: um feixe de luz verde-menta atravessa cinco painéis de vidro estampados em direção a um arco cor de marfim, enquanto uma lente de cobre examina um dos painéis.
Ilustração conceitual

Toda resposta do seu site traz cabeçalhos HTTP (os headers) que o visitante nunca vê. Alguns deles são instruções de segurança para o navegador: carregue scripts só destes endereços, use HTTPS neste host, não deixe outros sites colocarem esta página num frame, mantenha este cookie longe do JavaScript. Quando eles faltam, o navegador volta aos padrões mais permissivos. Quando estão errados, o login ou o checkout da loja podem parar de funcionar.

Este guia mostra como ler os cabeçalhos que o seu site realmente envia, o que cada um faz e quais valores são seguros para começar. Ele traz uma configuração base para nginx, para o .htaccess do Apache, comum em hospedagem compartilhada, e para hospedagens estáticas como Cloudflare Pages e Netlify, além dos erros que deixam algumas respostas sem cabeçalhos. Todos os exemplos usam example.com.

Escopo deste guia

O snapshot gratuito lê os cabeçalhos de uma única resposta: a página inicial da origem que você digitar, depois de até cinco redirecionamentos. Ele verifica principalmente se cada cabeçalho está presente, não se os valores servem para o seu site, e não é um pentest.

1. Verifique os cabeçalhos você mesmo: DevTools e curl

No Chrome ou no Edge, abra o DevTools, vá ao painel Network e recarregue a página. Clique na primeira requisição (o documento HTML), abra a aba Headers e role até Response Headers. Se o DevTools estiver em português, esses nomes podem aparecer traduzidos. Marque Preserve log para manter as requisições entre carregamentos e redirecionamentos, e Disable cache para receber uma resposta nova em vez de uma cópia em cache (referência do painel Network do Chrome DevTools). O Monitor de rede do Firefox funciona do mesmo jeito.

No terminal, o curl mostra exatamente o que o servidor envia:

curl -sS -D - -o /dev/null https://example.com/

Acrescente -L para seguir os redirecionamentos e ver os cabeçalhos de cada salto. No Windows, chame curl.exe e use -o NUL. O curl -I é mais curto, mas envia uma requisição HEAD em vez de GET, e algumas aplicações tratam HEAD por outro caminho no código; por isso, confirme com um GET o que você encontrar.

Repita a verificação para o endereço http:// (ele deve responder com um redirecionamento 301 ou 308 para HTTPS), para o outro nome do host (www ou o domínio sem www), para uma página que não existe, a página de login, uma resposta da API e um arquivo estático. A aplicação, o servidor web e a CDN muitas vezes colocam cabeçalhos diferentes em cada um desses casos, e só vale o que chega ao navegador.

2. O que cada cabeçalho faz e um valor seguro para começar

CabeçalhoO que fazValor inicial seguro
Content-Security-PolicyLimita de onde scripts, estilos, frames e outros recursos podem ser carregadosUma política de rascunho, enviada primeiro como Content-Security-Policy-Report-Only
CSP frame-ancestorsDefine quais sites podem incorporar a página num frame (defesa contra clickjacking)frame-ancestors 'self' ou 'none'
X-Frame-OptionsControle de frames mais antigo, mantido como alternativa para navegadores antigosSAMEORIGIN ou DENY, coerente com o frame-ancestors
Strict-Transport-SecurityDiz ao navegador para usar só HTTPS neste host durante max-age segundosmax-age=300, aumentado por etapas
X-Content-Type-OptionsImpede que o navegador adivinhe o tipo MIME; bloqueia scripts e folhas de estilo servidos com o tipo erradonosniff
Referrer-PolicyControla quanto da URL da página vai para outros sites no cabeçalho Refererstrict-origin-when-cross-origin
Permissions-PolicyDesliga recursos do navegador, como a câmera, para a página e os frames delacamera=(), microphone=(), geolocation=()
Cross-Origin-Opener-PolicyIsola a sua janela de pop-ups de outras origens e da página que a abriusame-origin, ou same-origin-allow-popups para pop-ups de login OAuth ou de pagamento
Atributos do Set-CookieLimitam como os cookies de sessão trafegam e quem pode lê-losSecure; HttpOnly; SameSite=Lax
X-XSS-ProtectionControlava um filtro de navegadores antigos; hoje está obsoletoRemova, ou envie 0

Com nosniff, o navegador confia no Content-Type declarado e bloqueia scripts e folhas de estilo que chegam com o tipo errado; por isso, confira esses tipos antes de ativá-lo. Sem um cabeçalho Referrer-Policy, os navegadores atuais já usam strict-origin-when-cross-origin; a OWASP ainda sugere enviá-lo de forma explícita por causa dos navegadores antigos, e no-referrer é mais restritivo se nada do que você usa depender do referrer. No Permissions-Policy, () desativa o recurso na página e em todos os frames dentro dela; libere um recurso só para a origem do widget que precisa dele. O COOP same-origin ajuda contra ataques de vazamento entre origens (XS-Leaks), mas pode quebrar pop-ups de login ou de pagamento servidos de outra origem, como a janela de checkout de um gateway de pagamento.

3. Content-Security-Policy e frame-ancestors

A CSP diz ao navegador de onde a página pode carregar scripts, estilos, imagens, frames e conexões. Ela limita o que um script injetado consegue fazer; não substitui o escape e a validação de entradas. O guia de CSP do MDN recomenda uma CSP estrita, baseada num nonce novo a cada resposta ou em hashes, em vez de uma longa lista de hosts permitidos. 'unsafe-inline' anula boa parte do objetivo, e o navegador o ignora em qualquer diretiva que também tenha um nonce ou hash. O que costuma dificultar uma política estrita é código de terceiros que carrega outros scripts, como gerenciadores de tags, pixels de anúncios e widgets de chat; por isso, anote o motivo de cada exceção que você acrescentar.

default-src serve de reserva (fallback) para as diretivas de busca, como script-src, mas não para o frame-ancestors: uma política com default-src 'none' ainda deixa qualquer site colocar a página num frame. Defina frame-ancestors 'self' de forma explícita, ou 'none', que é semelhante a X-Frame-Options: DENY (MDN). A OWASP HTTP Headers Cheat Sheet diz que o frame-ancestors torna o X-Frame-Options obsoleto nos navegadores que o suportam, enquanto o X-Frame-Options ainda cobre os navegadores antigos; se você enviar os dois, faça com que permitam o mesmo enquadramento. Duas armadilhas: o frame-ancestors, uma política report-only e o X-Frame-Options não têm efeito numa tag <meta>, e X-Frame-Options: ALLOW-FROM faz os navegadores modernos ignorarem o cabeçalho inteiro.

Um primeiro rascunho para um site sem scripts de terceiros é a política recomendada pelo OWASP Secure Headers Project:

default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests

Ela bloqueia scripts e estilos inline e tudo o que vem de outros hosts, então espere muitos relatórios no começo; é por isso que ela entra primeiro como Report-Only (seção 8). Aproveite só a linha da CSP: o conjunto completo do projeto também traz valores como Cache-Control: no-store e Clear-Site-Data, que desativariam o cache e apagariam os cookies e os dados armazenados do visitante em toda resposta. Em respostas JSON de API, que o navegador não renderiza, a CSP faz pouca diferença.

4. HSTS: aumente o max-age aos poucos e pense duas vezes antes do preload

O Strict-Transport-Security diz ao navegador para usar só HTTPS no host e converter automaticamente as próximas requisições http://. O navegador ignora o cabeçalho quando ele chega por HTTP simples; por isso, envie-o nas respostas HTTPS, não no redirecionamento de HTTP para HTTPS. Sozinho, ele não protege a primeiríssima conexão de um visitante.

Planeje o custo: num host com HSTS, o visitante não consegue passar por cima de um erro de certificado, então um certificado vencido deixa sem acesso quem já visitou o site. Certificados TLS públicos emitidos desde 15 de março de 2026 podem valer no máximo 200 dias (CA/Browser Forum), e o Let’s Encrypt não envia mais e-mails de aviso de expiração; por isso, deixe a renovação automática e o seu próprio monitoramento de validade funcionando antes. O guia de certificado SSL/TLS e cabeçalhos de segurança trata da parte dos certificados.

Aumente o max-age (em segundos) por etapas, como recomenda o hstspreload.org, e veja se algo quebrou a cada passo: 300 (5 minutos), 604800 (1 semana), 2592000 (1 mês) e depois 31536000 (1 ano) ou 63072000 (2 anos, o valor que a OWASP usa). max-age=0 remove a política, mas só quando enviado por HTTPS e só para os visitantes que voltarem e o receberem. Acrescente includeSubDomains quando todos os subdomínios funcionarem por HTTPS, e faça cada subdomínio enviar também o próprio cabeçalho.

O preload embute o seu domínio nos navegadores, para que até a primeira visita use HTTPS. O site de inscrição, hstspreload.org, agora recomenda o HSTS, mas não o preload: Chrome e Safari já convertem navegações HTTP em HTTPS, então o preload acrescenta pouco, e uma remoção da lista leva meses para chegar aos usuários. A OWASP HTTP Headers Cheat Sheet ainda inclui preload no cabeçalho de exemplo, enquanto o valor recomendado pelo OWASP Secure Headers Project o deixa de fora. Não o acrescente por padrão nem o copie de um modelo pronto; tutoriais e traduções mais antigos podem não refletir essa mudança, então confira a data da fonte.

5. Atributos de cookie: Secure, HttpOnly e SameSite

Set-Cookie: __Host-session=…; Path=/; Secure; HttpOnly; SameSite=Lax
  • Secure faz o navegador enviar o cookie só por HTTPS (exceto em localhost). Ele não esconde o cookie do JavaScript.
  • HttpOnly impede que scripts da página leiam o cookie (por exemplo, via document.cookie), mas o navegador continua enviando-o nas requisições correspondentes; assim, ele limita o roubo de cookies por XSS sem impedir o XSS em si.
  • SameSite define se o cookie acompanha requisições entre sites. Com Strict, nunca acompanha. Com Lax, acompanha também as navegações GET de nível superior vindas de outro site, como um visitante que clica num link para o seu. Com None, acompanha sempre, e None exige Secure. Os navegadores divergem no valor padrão, então defina-o de forma explícita.
  • O prefixo de nome __Host- faz o navegador rejeitar o cookie, a menos que ele seja definido com Secure a partir de uma origem HTTPS, com Path=/ e sem o atributo Domain.

Use Lax ou Strict nos cookies de sessão, a não ser que um fluxo realmente precise de None, por exemplo o retorno de um pagamento ou de um login que faz POST de volta a partir de outro site. A OWASP Session Management Cheat Sheet trata o SameSite como defesa em profundidade contra falsificação de requisição entre sites (CSRF), não como substituto dos tokens anti-CSRF.

6. Cabeçalhos para remover: X-XSS-Protection e outras sobras

  • X-XSS-Protection ativava um filtro em navegadores antigos que podia, ele mesmo, criar vulnerabilidades de XSS (MDN). A OWASP recomenda não enviá-lo, ou desativá-lo com 0; a CSP é a substituta.
  • Expect-CT: a OWASP recomenda não usá-lo e, citando a Mozilla, removê-lo das configurações existentes.
  • Public-Key-Pins (HPKP) foi removido do Chromium em 2018 e não é suportado por nenhum navegador moderno.
  • Feature-Policy foi substituído pelo Permissions-Policy.

Os cabeçalhos Server e X-Powered-By revelam o software que você usa, às vezes com o número da versão. A OWASP sugere removê-los ou deixá-los sem informação útil, mas o próprio guia de testes da OWASP chama isso de segurança por obscuridade, e o MDN diz que manter o software atualizado importa mais. Tire os números de versão (no nginx, server_tokens off; remove a versão, não o cabeçalho) e invista o esforço em atualizações.

7. Uma configuração base para nginx, Apache e hospedagens estáticas

Esta base para nginx define os cabeçalhos de baixo risco, começa o HSTS e a CSP nas fases de teste e redireciona HTTP para HTTPS no mesmo host. O parâmetro always acrescenta os cabeçalhos também às respostas de erro.

server {
    listen 80;
    server_name example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    # ssl_certificate e ssl_certificate_key entram aqui
    server_tokens off;

    add_header Strict-Transport-Security "max-age=300" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Content-Security-Policy-Report-Only "default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'" always;
}

Dois comportamentos documentados do módulo de cabeçalhos do nginx explicam muitos cabeçalhos ausentes. Sem always, o add_header vale só para os códigos 200, 201, 204, 206, 301, 302, 303, 304, 307 e 308, então as páginas 404 e 500 saem sem os cabeçalhos. E as diretivas add_header só são herdadas do nível de cima se o nível atual não definir nenhuma: um único add_header dentro de um bloco location derruba ali todos os cabeçalhos de segurança definidos no server. Repita os cabeçalhos, use include com um arquivo compartilhado ou, a partir do nginx 1.29.3, use add_header_inherit merge;.

Em hospedagem compartilhada com Apache, os cabeçalhos costumam ir no arquivo .htaccess. Segundo a documentação do mod_headers, a diretiva Header é aceita nesse arquivo quando a hospedagem libera esse tipo de configuração (AllowOverride FileInfo), e a condição always faz o cabeçalho sair também nas respostas de erro:

Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy-Report-Only "default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'"

Depois de salvar, confira o resultado com curl. Se o CMS ou um plugin de segurança também definir algum desses cabeçalhos, ele pode sair duplicado; escolha uma camada só para cada cabeçalho.

Hospedagens estáticas como Cloudflare Pages e Netlify leem um arquivo _headers publicado junto com o site. Este exemplo segue o formato documentado pela Cloudflare, que a Netlify também usa:

/*
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
  X-Frame-Options: SAMEORIGIN
  Content-Security-Policy-Report-Only: default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'

Conheça os limites. O Cloudflare Pages não aplica o arquivo às respostas geradas por Pages Functions, aceita até 100 regras de cabeçalho com no máximo 2.000 caracteres por linha e junta os valores com vírgula quando o mesmo cabeçalho é aplicado duas vezes. A Netlify só aplica cabeçalhos personalizados aos arquivos que ela mesma serve, não a conteúdo via proxy, functions, edge functions ou páginas renderizadas no servidor; essas respostas precisam definir os próprios cabeçalhos. O HSTS ficou fora dos exemplos do Apache e das hospedagens estáticas: veja com curl o que a plataforma já envia antes de acrescentá-lo.

8. Implante por etapas e evite os erros comuns

  1. Acrescente nosniff, Referrer-Policy, Permissions-Policy e a proteção contra frames e, em seguida, teste login, checkout e widgets incorporados.
  2. Envie a CSP de rascunho como Content-Security-Policy-Report-Only. Nada é bloqueado; as violações aparecem no console do navegador e, se a política indicar um, num endpoint de relatórios. Percorra as jornadas principais, incluindo as páginas atrás do login, e ajuste a política.
  3. Comece o HSTS com um max-age curto e aumente por etapas.
  4. Passe a aplicar a CSP de verdade. Uma política Report-Only mais restrita pode rodar ao lado dela para testar a próxima rodada de restrições.
  5. Rode de novo as verificações com curl depois de cada mudança no servidor, na CDN ou no framework.

Erros comuns:

  • Cabeçalhos só em algumas respostas. A página inicial tem; a página 404, a API, os arquivos estáticos ou uma página de login servida separadamente não têm.
  • Trocar host e protocolo num único redirecionamento. Se http://example.com redireciona direto para https://www.example.com, o navegador nunca recebe o HSTS de example.com. Redirecione primeiro para HTTPS no mesmo host, envie o HSTS nessa resposta HTTPS e só então redirecione para o www.
  • A CDN sobrescreve a origem. Uma CDN ou um proxy podem acrescentar, trocar, remover ou duplicar cabeçalhos. Defina qual camada é dona de cada cabeçalho e confirme o resultado com curl.
  • Uma CSP que libera tudo. Uma política recheada de 'unsafe-inline', 'unsafe-eval' ou * para silenciar erros passa numa verificação de presença, mas bloqueia pouco.
  • includeSubDomains cedo demais. Um subdomínio esquecido que só funciona por HTTP fica inacessível para os navegadores que armazenaram a política.

Cabeçalhos são uma camada. O checklist de lançamento de site coloca os cabeçalhos ao lado de DNS, TLS e redirecionamentos, e o guia de auditoria de segurança de site cobre login, permissões e uma rotina de revisão que pode ser repetida.

9. Como o snapshot gratuito do Sitelemetry verifica os cabeçalhos

O snapshot gratuito de prontidão para lançamento roda oito verificações passivas em uma origem pública, sem cadastro; uma delas lê os cabeçalhos de segurança HTTP. Ele não é um pentest nem a auditoria das seis áreas.

  • Ele requisita a página inicial da origem que você digitar (caminhos e query strings são descartados), segue até cinco redirecionamentos e avalia a resposta final. Nenhuma outra página é requisitada.
  • Ele verifica principalmente a presença. CSP ausente, HSTS ausente num endereço HTTPS, falta de proteção contra frames e Access-Control-Allow-Origin: * são classificados como médios. X-Content-Type-Options diferente de nosniff, Referrer-Policy ausente e qualquer cabeçalho Server ou X-Powered-By são classificados como baixos; assim, Server: nginx sem versão ainda gera um sinal baixo. Cookies definidos nessa resposta sem HttpOnly, ou sem Secure em HTTPS, são classificados como médios; o SameSite não é verificado.
  • Uma nota de blindagem separada (de A a F) pontua os cabeçalhos presentes junto com o resultado do TLS e dá menos crédito à CSP quando ela permite 'unsafe-inline' (ou 'unsafe-eval' para scripts). Permissions-Policy e COOP contam só nessa nota.
  • A verificação separada de redirecionamento HTTPS depende do que você digita. Para um domínio sem protocolo ou um endereço https://, ela aponta como baixo um max-age do HSTS abaixo de 180 dias, o que é esperado durante o aumento gradual, e procura referências http:// no HTML da página (conteúdo misto); ela não testa o redirecionamento de HTTP para HTTPS. O redirecionamento só é testado quando você digita o endereço http://, e essa execução pula a verificação de TLS e não aponta HSTS ausente.

O resultado mostra uma pontuação, a nota de blindagem, o número de sinais de risco e de verificações aprovadas e até três sinais, com os riscos primeiro. Ele não lista cada cabeçalho e o seu valor; para isso, e para as respostas que o snapshot não requisita, use o DevTools ou o curl.

Perguntas frequentes

Como verificar os cabeçalhos de segurança do meu site?

No DevTools do navegador, abra o painel Network, recarregue a página, selecione o documento HTML e leia os Response Headers. No terminal, o comando curl -sS -D - -o /dev/null https://example.com/ mostra os cabeçalhos. Verifique também o endereço http://, uma página 404, uma resposta da API e um arquivo estático, porque os cabeçalhos costumam mudar entre eles.

Quais cabeçalhos de segurança HTTP devo configurar primeiro?

Comece por X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy e a proteção contra frames, que são os que menos costumam quebrar alguma coisa; mesmo assim, teste scripts, login e widgets incorporados depois. Em seguida, teste uma Content-Security-Policy em modo Report-Only e aumente o max-age do HSTS por etapas.

Ainda devo enviar o X-XSS-Protection?

Não. Remova o cabeçalho ou envie X-XSS-Protection: 0 e conte com uma Content-Security-Policy. O antigo filtro de navegador que ele controlava podia, ele mesmo, criar vulnerabilidades de XSS.

Preciso do X-Frame-Options se já uso frame-ancestors?

A diretiva frame-ancestors da CSP o substitui nos navegadores que a suportam. X-Frame-Options: DENY ou SAMEORIGIN continua sendo uma alternativa razoável para navegadores antigos, desde que os dois cabeçalhos permitam o mesmo enquadramento. Não use ALLOW-FROM: os navegadores modernos ignoram o cabeçalho inteiro quando o encontram.

Devo colocar meu domínio na lista de preload do HSTS?

Normalmente, não. O próprio site de inscrição, hstspreload.org, agora recomenda o HSTS, mas não o preload, porque Chrome e Safari já convertem navegações HTTP em HTTPS. Uma remoção da lista também leva meses para chegar aos usuários.

Cabeçalhos de segurança deixam meu site seguro?

Não sozinhos. Eles limitam o estrago de scripts injetados, clickjacking, rebaixamento de protocolo e roubo de cookies. Não corrigem código vulnerável, software desatualizado nem controle de acesso fraco.

Fontes e leituras

  1. MDN: guia de Content Security Policy (CSP)developer.mozilla.org
  2. MDN: diretiva frame-ancestors da CSPdeveloper.mozilla.org
  3. MDN: cabeçalho Strict-Transport-Securitydeveloper.mozilla.org
  4. MDN em português: Strict-Transport-Securitydeveloper.mozilla.org
  5. MDN em português: Content-Security-Policydeveloper.mozilla.org
  6. MDN: cabeçalho Set-Cookie e atributos de cookiedeveloper.mozilla.org
  7. OWASP HTTP Headers Cheat Sheetcheatsheetseries.owasp.org
  8. OWASP Secure Headers Project: valores recomendadosraw.githubusercontent.com
  9. HSTS Preload List Submissionhstspreload.org
  10. nginx: ngx_http_headers_module (add_header)nginx.org
  11. Apache HTTP Server: mod_headershttpd.apache.org
  12. Cloudflare Pages: Headersdevelopers.cloudflare.com
  13. Netlify: Custom headersdocs.netlify.com
Equipe Sitelemetry

Preparado pela equipe editorial do Sitelemetry. Consulte as fontes indicadas para aprofundar o assunto.

SITELEMETRY

Coloque o aprendizado em prática.

Explore a estrutura, as configurações e os sinais do seu site com o Sitelemetry.