Guia de correção

Como configurar cabeçalhos HTTP de segurança via .htaccess vs Nginx

20 de maio de 2026

Cabeçalhos HTTP de segurança são cabeçalhos de resposta que dizem aos navegadores para impor comportamentos de segurança específicos ao renderizar uma página. São configurados no servidor web, não no WordPress, e não custam performance ao serem ativados. Um site WordPress com cabeçalhos corretos bloqueia clickjacking, downgrades para conteúdo misto, exploits de MIME-sniffing e uma grande parte de payloads de cross-site scripting. A configuração é uma mudança única no .htaccess do Apache ou na config do servidor do Nginx. Abaixo estão os sete cabeçalhos que importam em 2026, com snippets prontos para copiar-colar para ambos os servidores web.

Quais cabeçalhos HTTP de segurança um site WordPress deve definir?

Sete cabeçalhos cobrem o modelo de ameaça realista para um site orientado a conteúdo. Em ordem de prioridade:

  • Strict-Transport-Security (HSTS). Força navegadores a usar HTTPS por um ano (ou mais) após a primeira visita, prevenindo ataques de HTTPS-stripping em WiFi público. Obrigatório se seu site tem usuários logados.
  • Content-Security-Policy (CSP). Diz ao navegador exatamente quais fontes de JavaScript, CSS, imagens e fontes são permitidas. O cabeçalho mais impactante contra XSS, mas também o mais complicado de configurar sem quebrar seu site.
  • X-Frame-Options ou a diretiva CSP frame-ancestors. Impede seu site de ser embutido num iframe em outro domínio, bloqueando ataques de clickjacking contra o formulário de login.
  • X-Content-Type-Options: nosniff. Impede navegadores de adivinhar o tipo de conteúdo de uma resposta, fechando uma classe de ataques de "envie uma imagem falsa que na verdade é JavaScript".
  • Referrer-Policy. Controla quanto da URL atual é enviado no cabeçalho Referer em cliques de saída. Padrões vazam query strings para terceiros; strict-origin-when-cross-origin é a recomendação moderna.
  • Permissions-Policy (anteriormente Feature-Policy). Desabilita funções do navegador que seu site não usa (câmera, microfone, geolocalização), reduzindo a exposição se algum script de terceiros alguma vez tentar acessá-las.
  • Cross-Origin-Opener-Policy. Isola seu site de quaisquer janelas popup que abre, mitigando ataques de canal lateral classe Spectre. Requerido para que SharedArrayBuffer funcione.

O que não é mais recomendado: X-XSS-Protection (deprecado, navegadores ignoram), Public-Key-Pins (deprecado, causou muitos bloqueios) e Expect-CT (deprecado desde 2023).

Apache .htaccess: bloco copiar-colar de cabeçalhos de segurança

Adicione isto ao topo do seu .htaccess na raiz do WordPress, acima do bloco WordPress (# BEGIN WordPress). O guard IfModule garante que o snippet não quebra se mod_headers estiver faltando.

<IfModule mod_headers.c>
    # HSTS: forçar HTTPS por 1 ano, incluir subdomínios, pronto para preload
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

    # Prevenir clickjacking
    Header always set X-Frame-Options "SAMEORIGIN"

    # Bloquear MIME-sniffing
    Header always set X-Content-Type-Options "nosniff"

    # Limitar vazamento de referrer
    Header always set Referrer-Policy "strict-origin-when-cross-origin"

    # Desabilitar funções do navegador não usadas
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()"

    # Isolamento cross-origin
    Header always set Cross-Origin-Opener-Policy "same-origin"

    # CSP inicial conservadora; aperte uma vez que saiba o que seu site carrega
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';"
</IfModule>

A palavra-chave always é crítica. Sem ela, cabeçalhos só são enviados em respostas 2xx e 3xx; com ela, páginas de erro e redirecionamentos também carregam os cabeçalhos. Sem always, um atacante que dispara um erro 500 vê uma resposta desprotegida.

O módulo mod_headers deve estar habilitado. Em hospedagem compartilhada geralmente já está. Em Apache autogerenciado: sudo a2enmod headers && sudo systemctl reload apache2.

Nginx: bloco copiar-colar de cabeçalhos de segurança

Adicione isto dentro do bloco server { ... } do seu site, tipicamente em /etc/nginx/sites-available/seusite.conf:

    # HSTS: forçar HTTPS por 1 ano, incluir subdomínios, pronto para preload
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Prevenir clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Bloquear MIME-sniffing
    add_header X-Content-Type-Options "nosniff" always;

    # Limitar vazamento de referrer
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Desabilitar funções do navegador não usadas
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;

    # Isolamento cross-origin
    add_header Cross-Origin-Opener-Policy "same-origin" always;

    # CSP inicial conservadora; aperte uma vez que saiba o que seu site carrega
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';" always;

O always final no Nginx serve o mesmo propósito que no Apache: faz o cabeçalho aplicar também a respostas de erro. Recarregue o Nginx após a mudança: sudo nginx -t && sudo systemctl reload nginx.

A regra de duas pegadinhas do Nginx add_header

O Nginx tem uma peculiaridade que morde as pessoas repetidamente. Duas regras para internalizar antes de tocar em config de produção:

  • add_header é substituído, não mesclado. Se você define cabeçalhos no bloco server e novamente em um bloco location, os cabeçalhos do bloco location substituem os do bloco server para aquela localização. Eles não se somam. O sintoma: cabeçalhos funcionam em todo lugar exceto dentro de uma localização específica (como /wp-admin/ onde você adicionou uma regra personalizada).
  • Sempre adicione a flag always. Sem ela, uma página 404 ou uma página de erro 500 é servida sem seus cabeçalhos de segurança. Atacantes podem deliberadamente disparar erros para contornar proteções baseadas em cabeçalhos.

O Header always set do Apache é o equivalente à flag always do Nginx e tem o mesmo efeito.

Apache vs Nginx: qual é mais fácil de configurar?

Praticamente equivalentes para cabeçalhos de segurança. Ambos usam uma única diretiva por cabeçalho e aceitam valores de cabeçalho idênticos. Três diferenças que vale a pena conhecer:

  • Onde a config vive. Apache via .htaccess pode ser editado por diretório por qualquer um com acesso FTP à instalação do WordPress. Config Nginx vive fora da raiz do documento e geralmente requer SSH mais um reload. Para hospedagem WordPress compartilhada, .htaccess é mais prático; para setups Nginx gerenciados, a config do servidor é mais performante (Nginx não relê regras equivalentes a .htaccess a cada request, mantém a config nginx correta em memória).
  • Overrides por localização. Apache .htaccess herda automaticamente as configurações do diretório pai. Blocos location do Nginx precisam de re-declaração explícita se você customizar um (por causa da pegadinha de mesclagem acima).
  • Realidade da hospedagem. A maioria da hospedagem WordPress compartilhada (Hostinger, IONOS, GoDaddy, hosts cPanel tradicionais) é Apache. A maioria da hospedagem WordPress gerenciada (Kinsta, WP Engine, Raidboxes, SiteGround, Cloudways) é Nginx. A divisão de mercado mudou de maioria-Apache para aproximadamente 50/50 nos últimos cinco anos.

Devo adicionar cabeçalhos de segurança no WordPress em vez do servidor web?

Você pode, mas o nível do servidor web é melhor. Três opções do lado WordPress existem:

  • Plugin de segurança (Wordfence, iThemes Security, etc.). Tem uma funcionalidade "cabeçalhos de segurança" que adiciona os mesmos cabeçalhos do lado PHP. Funciona mas adiciona alguns milissegundos por request. Útil se você não tem acesso ao servidor web.
  • Código customizado de plugin ou tema. Um pequeno mu-plugin pode chamar header() em PHP para emitir cada cabeçalho. Mesma sobrecarga, mesmas ressalvas.
  • Config do servidor web (recomendado). Zero sobrecarga PHP, aplica-se a cada resposta incluindo erros 404 e arquivos estáticos, sobrevive a crashes do WordPress.

O argumento para o nível do servidor web: cabeçalhos adicionados em PHP não protegem respostas que contornam o PHP. Se um atacante alcança um arquivo estático diretamente (um backup .phps esquecido, um diretório de uploads com arquivos HTML), cabeçalhos definidos por PHP não se aplicam. O servidor web vê cada request e é a camada correta.

Como eu afino a Content-Security-Policy sem quebrar meu site?

CSP é o cabeçalho de segurança mais impactante e também o mais provável de quebrar coisas. Um site WordPress carrega scripts e estilos de dezenas de fontes por padrão: jQuery de /wp-includes, assets do tema, assets de plugins, Google Fonts (se não auto-hospedados), analytics, YouTube embutido, etc. Uma CSP estrita que não whiteliste estes explicitamente os bloqueará e o site parecerá quebrado de maneiras sutis (o login falha, a galeria não funciona, o analytics para).

O padrão de implantação em duas fases que funciona:

  1. Comece em modo report-only. Use Content-Security-Policy-Report-Only em vez de Content-Security-Policy. O navegador não bloqueia nada; apenas registra violações no console do desenvolvedor. Navegue pelo seu site por alguns dias, monitore o que teria sido bloqueado, e adicione as fontes legítimas à sua política.
  2. Mude para modo enforcing. Uma vez que o modo report-only mostre zero violações em uma navegação normal, mude o nome do cabeçalho de volta para Content-Security-Policy. Agora as violações são bloqueadas.

Uma armadilha comum: WordPress e muitos plugins usam handlers de eventos JavaScript inline (onclick="") e blocos <script> inline. Uma CSP estrita requer ou 'unsafe-inline' (derrota a maior parte da proteção) ou nonces para cada script inline (mudanças significativas de código). O meio-termo pragmático em 2026: mantenha 'unsafe-inline' por enquanto, mas trave as outras diretivas. Versões futuras do WordPress estão se movendo em direção a scripts inline amigáveis a nonces.

Como verifico que meus cabeçalhos de segurança estão funcionando?

Quatro métodos, do mais rápido ao mais autoritativo:

  1. Relatório InspectWP. A seção Segurança lista cada cabeçalho que seu site define, seu valor, e sinaliza os que faltam ou estão mal configurados. Uma tela.
  2. curl da linha de comando. curl -I https://seusite.com imprime os cabeçalhos de resposta. Procure pelos sete cabeçalhos acima; verifique seus valores.
  3. securityheaders.com. Um scanner público gratuito que dá nota ao seu site (A+ a F) e explica quais cabeçalhos estão faltando ou fracos. Padrão da indústria para auditorias de cabeçalhos.
  4. DevTools do navegador. Abra DevTools (F12), aba Network, clique no request do documento, olhe a seção Response Headers. Útil para ver violações CSP ao vivo na aba Console.

Erros e armadilhas comuns

  • Adicionar HSTS sem confirmar que HTTPS funciona em todo o site. HSTS força navegadores a usar HTTPS por um ano. Se seu site tem um certificado quebrado ou uma subpágina que só funciona sobre HTTP, usuários ficam trancados fora. Teste HTTPS exaustivamente antes de habilitar HSTS. Comece com um max-age curto (como 300 segundos) e suba para um ano.
  • Definir X-Frame-Options E CSP frame-ancestors. Ambos funcionam mas frame-ancestors é o equivalente moderno. Definir ambos é redundante mas inofensivo; navegadores modernos preferem frame-ancestors.
  • Esquecer includeSubDomains no HSTS. Se seu site principal é HTTPS mas um subdomínio ainda serve HTTP, atacantes podem pivotar pelo subdomínio. includeSubDomains força HTTPS em todo lugar sob seu domínio. Verifique que todos os subdomínios são HTTPS antes de adicionar isto.
  • Copiar uma CSP de um tutorial genérico. Cada site WordPress carrega assets de terceiros diferentes. Uma CSP genérica vai quebrar seu site. Use modo report-only primeiro.
  • Misturar cabeçalhos de CDN e origem. Se você tem Cloudflare na frente, pode definir cabeçalhos no Cloudflare (Page Rules ou Transform Rules) ou na origem. Definir ambos com valores diferentes causa confusão ao debugar. Escolha um lugar e documente.
  • Esquecer de recarregar após editar. Mudanças Nginx não fazem nada até systemctl reload nginx. Mudanças .htaccess do Apache são instantâneas; mudanças na config principal do Apache requerem um reload.

E sobre HTTP/3 e a história moderna de cabeçalhos?

HTTP/3 não muda nada sobre quais cabeçalhos definir; a semântica de cabeçalhos é idêntica em HTTP/1.1, HTTP/2 e HTTP/3. Um cabeçalho que se torna relevante em HTTP/3 é Alt-Svc, que anuncia disponibilidade de HTTP/3 a clientes que chegaram via HTTP/2. A maioria dos servidores web adiciona isso automaticamente.

A paisagem de navegadores também está se movendo gradualmente para impor padrões modernos mesmo quando cabeçalhos estão faltando. Chrome e Firefox agora usam por padrão strict-origin-when-cross-origin para Referrer-Policy se nenhum cabeçalho é enviado, e cada vez mais assumem HTTPS para qualquer site que tenha sido servido sobre HTTPS alguma vez. Definir os cabeçalhos explicitamente ainda é recomendado porque os padrões variam por versão de navegador e porque clientes HTTP não-navegador (curl, scripts, ferramentas de monitoramento) não implementam esses padrões.

O que o InspectWP verifica

A seção Segurança de cada relatório InspectWP inspeciona os cabeçalhos de resposta do seu documento principal e reporta quais dos cabeçalhos de segurança padrão estão presentes, quais são seus valores, e quais estão faltando ou definidos para valores não recomendados. HSTS faltando em um site HTTPS é sinalizado como aviso; X-Content-Type-Options faltando é sinalizado como informativo; uma CSP definida como default-src * (efetivamente nenhuma política) é sinalizada como má configuração. O relatório também nota quando cabeçalhos são definidos no nível CDN versus no nível origem, já que isso afeta o que você precisaria mudar para atualizá-los. O estado recomendado é os sete cabeçalhos presentes com valores razoáveis, e CSP ou em modo report-only enquanto você a afina ou em modo enforcing uma vez afinada.

Verifique seu site WordPress agora

O InspectWP analisa seu site WordPress em busca de problemas de segurança, problemas de SEO, conformidade com GDPR e desempenho — gratuitamente.

Analise seu site grátis