Noções de segurança
Cabeçalhos de segurança faltando: quando isso importa
Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.

Em resumo
- Cabeçalhos de segurança faltando é o achado mais comum que existe e, sozinho, ele quase não diz nada sobre alguém conseguir chegar aos seus dados.
- Escaneamos 30.998 apps no ar. Dois em cada três dos que estavam sem cabeçalhos não tinham mais nada de errado.
- Ainda assim vale corrigir, e isso vem depois das coisas que decidem quem pode ler o seu banco de dados.
- Em alguns domínios de builders você não consegue defini-los, e deixar como está é uma resposta razoável.
Seu scan volta e quase todas as linhas estão verdes. Uma está âmbar: alguns cabeçalhos de segurança do navegador estão faltando. É a única coisa colorida da página, então parece a primeira de que cuidar.
Aqui está a parte que a maioria dos conselhos sobre isso erra. Cabeçalhos de segurança faltando é o achado que mais imprimimos e, sozinho, ele quase não diz nada sobre alguém conseguir chegar aos seus dados. Tratar isso como uma invasão significa ou corrigir no susto, na frente das coisas que de fato decidem quem lê o seu banco de dados, ou aprender que linhas âmbar são ruído, o que é pior.
Entre 12 e 14 de agosto de 2026 rodamos as mesmas nove verificações externas em 30.998 apps no ar feitos com Lovable, Bolt, v0, Replit e Base44. Dos apps em que essa verificação obteve resposta, 30.756 de 30.981 estavam sem pelo menos um cabeçalho. Os números completos estão no nosso relatório de varredura.
Cabeçalhos de segurança faltando são um problema?
É uma lacuna real e quase sempre a linha menos urgente do seu relatório.
Um cabeçalho de segurança é uma instrução curta que o seu servidor anexa a cada página que envia, endereçada ao navegador de quem visita e não à pessoa. Não deixe outro site colocar esta página dentro de um quadro. Não adivinhe que tipo de arquivo é este. Não passe o meu endereço completo quando alguém clicar para fora. São bilhetes para um ajudante que faz o que qualquer site mandar.
O resto do seu relatório é sobre fechaduras. Se o Row Level Security está ligado, se tem uma chave secreta no seu código, se um bucket de armazenamento lista o conteúdo: é isso que decide quem consegue chegar aos seus dados. Bilhete e fechadura a gente quer os dois, e o bilhete que você nunca escreveu não é o motivo pelo qual se perde um banco de dados.
Nossa nota trata assim. Um cabeçalho faltando tira cinco pontos de cem e não limita o teto, então um app cujo único achado é esse sai com 95 e nota A.
O que encontramos em 30.998 apps
Cabeçalhos faltando apareceram em quase tudo, e mal se mexeram junto com o resto do relatório.
25.821 desses apps obtiveram resposta das nove verificações, e é esse o grupo em que "não tinha mais nada" significa alguma coisa. Entre eles, 25.606 estavam sem pelo menos um cabeçalho e 215 tinham os cinco.
Dos 25.606 apps sem pelo menos um cabeçalho, 17.043 não tinham mais nada de errado. Dois em cada três. Era o único problema do relatório deles.
Agora leia a outra linha, que é a parte que nos surpreendeu. Dos 215 apps que tinham os cinco cabeçalhos definidos, 145 tinham outra coisa errada. Essa é uma taxa de problemas reais mais alta do que entre os apps sem cabeçalhos, e não mais baixa.
Não medimos o porquê, e a leitura honesta é estreita: seja lá o que essas varreduras encontraram, o achado sobre cabeçalhos não previu isso. Um app com um conjunto perfeito de cabeçalhos não era um app mais seguro nos nossos dados. A explicação mais provável é que definir cabeçalhos já significa que alguém configurou uma hospedagem de verdade, o que costuma significar um app maior com mais coisa para dar errado, mas isso é um palpite e não testamos.
Se você quiser ver quais dessas linhas o seu próprio app produz, o scan é gratuito, leva uns 20 segundos e não precisa de conta: escaneie seu app.
O que cada cabeçalho realmente faz
Cada um desliga um comportamento do navegador que vem ligado de fábrica.
| Cabeçalho | O que ele diz ao navegador | O que a ausência dele permite |
|---|---|---|
Content-Security-Policy | De quais lugares esta página pode carregar código e estilos | Um script injetado consegue mandar dados para onde quiser |
Strict-Transport-Security | Volte sempre por HTTPS, nunca por HTTP puro | Uma visita numa rede não confiável pode ser empurrada para HTTP puro |
X-Frame-Options | Não deixe outro site exibir esta página dentro de um quadro | Sua página pode ser carregada invisível dentro da de outra pessoa |
X-Content-Type-Options | Confie no tipo de arquivo que eu passei e não adivinhe pelo conteúdo | Um arquivo que alguém subiu pode ser servido como um tipo de arquivo diferente |
Referrer-Policy | Quanto deste endereço repassar quando alguém clicar para fora | URLs completas, com tudo que houver nelas, chegam a servidores de terceiros |
Dois deles se sobrepõem, e o scanner leva isso em conta. Uma
Content-Security-Policy que contenha frame-ancestors faz o mesmo trabalho de
X-Frame-Options, então a nossa verificação conta qualquer um dos dois e não
exige os dois.
Quando um cabeçalho faltando é o problema inteiro
Quando o seu app tem algo que vale a pena clicar enquanto a pessoa está logada.
Esse é o caso do clickjacking, e é o único que funciona sem nenhum outro erro. Alguém carrega o seu app num quadro invisível dentro de uma página que controla e põe os botões dele por cima dos seus, de modo que quem já está logado clica no que parece a página dele e acerta um controle seu: o botão que apaga uma conta, aprova uma transferência ou troca um endereço de e-mail.
Quem visita está logado, então a ação carrega a sessão dessa pessoa. Nada no seu banco de dados precisa estar mal configurado. O que faz isso funcionar é que nunca disseram ao navegador para recusar.
Referrer-Policy tem uma versão menor do mesmo formato. Se uma página sua com
sessão aberta carrega algo identificável na URL e aponta para um servidor de
imagens ou um script de analytics, o endereço inteiro viaja junto com o clique.
Quem opera aquele outro servidor vê onde o seu usuário estava.
Os outros três são condicionais. Eles importam quando outra coisa já deu errado,
e o trabalho deles é manter isso pequeno. Uma Content-Security-Policy limita o
que um script injetado consegue fazer com o acesso que tem.
X-Content-Type-Options importa se estranhos podem subir arquivos para você.
Strict-Transport-Security cobre quem usa o seu app numa rede que não controla.
Eu preciso de cabeçalhos de segurança?
Precisa. Eles são baratos, e vêm depois dos achados que decidem quem pode ler o seu banco de dados.
A ordem que sai da medição acima: primeiro tudo que estiver como crítico ou alto no seu relatório, cabeçalhos depois. Se o seu relatório tem só essa linha, como foi o caso de 17.043 dos apps que escaneamos, então os cabeçalhos ficam no topo da sua lista por eliminação.
Dois dos cinco não custam nada para acertar.
X-Content-Type-Options: nosniff e
Referrer-Policy: strict-origin-when-cross-origin são uma linha cada, não têm
valor errado a escolher e não conseguem quebrar um app que funciona.
X-Frame-Options: DENY também é uma linha, e vale olhar antes se você embute o
seu próprio app em algum lugar de propósito.
Content-Security-Policy é o que dá trabalho de verdade. Uma primeira tentativa
costuma bloquear algo de que a sua própria página precisava, e o sintoma é uma
função que para de funcionar sem avisar. Suba como
Content-Security-Policy-Report-Only, que conta o que teria bloqueado sem
bloquear nada, e leia uma semana de relatórios antes de ligar.
Como adicioná-los
Naquilo que de fato serve o seu app para a internet, que muitas vezes não é o lugar onde você o constrói.
A maioria dos builders publica numa hospedagem que é dona da resposta, então a
configuração mora lá. Na Vercel é headers dentro do vercel.json. No Netlify
e no Cloudflare Pages é um arquivo _headers na raiz do que você publica. Atrás
do proxy da Cloudflare é uma Transform Rule. Se você roda um servidor próprio, é
a sua configuração de nginx ou Caddy.
O que dá para saber sobre cabeçalhos depois de defini-los é que eles saem sem ninguém encostar neles. Mudar para um domínio próprio, colocar um proxy na frente, trocar de hospedagem, mexer numa configuração de framework: os cabeçalhos que você adicionou moram em um desses lugares, e qualquer um desses passos pode deixá-los para trás. Nada te avisa. A página continua funcionando e a configuração sumiu.
É para esse tipo de coisa que existe o Reeve Monitor. Ele roda a verificação completa de novo a cada hora em até três apps, acompanha a disponibilidade a cada 60 segundos e te avisa quando um resultado muda, em vez de esperar você olhar. O Monitor só acompanha, então se você também quiser uma cópia do seu banco de dados em algum lugar que o seu builder não alcance, isso é o Care, e ele cobre o Supabase.
O que fazer agora
O que fazer
- Leia primeiro o resto do relatório. Se tiver algo marcado como crítico ou alto, o trabalho é esse, e os cabeçalhos esperam.
- Coloque hoje
X-Content-Type-Options: nosniffeReferrer-Policy: strict-origin-when-cross-origin. Uma linha cada, nada a decidir, nada a quebrar. - Coloque
X-Frame-Options: DENYse as pessoas fazem login no seu app e conseguem fazer algo pesado com um clique. - Deixe
Content-Security-Policypor último e comece em modo report-only, para descobrir antes dos seus visitantes o que ele quebra. - Se você está num subdomínio de builder sem configuração de cabeçalhos, deixe o achado quieto. Ele ainda não é seu.
- Confira de novo depois de mudar de domínio, adicionar um proxy ou trocar de hospedagem. É aí que eles somem.
Cabeçalhos valem uma tarde tranquila quando o resto do relatório estiver limpo. Se você prefere percorrer a lista inteira em ordem, a checklist de segurança de 10 minutos cobre o que desligar num app recém-lançado, e os achados que de fato decidem quem lê o seu banco de dados são os primeiros a tirar do caminho.
Perguntas frequentes
Meu scan diz que estão faltando cabeçalhos de segurança. Meu app foi hackeado?
Não. Um cabeçalho faltando é uma configuração que nunca foi ligada, e não é prova de que algo aconteceu. Nada no achado envolve alguém chegando aos seus dados ou à sua conta. Ele descreve uma instrução que o seu site poderia estar dando aos navegadores que o visitam e no momento não dá.
Qual cabeçalho de segurança eu devo colocar primeiro?
X-Content-Type-Options e Referrer-Policy, porque os dois são uma linha só, nenhum tem um valor errado a escolher e nenhum consegue quebrar um app que funciona. Depois X-Frame-Options, se as pessoas fazem login no seu app. Depois Strict-Transport-Security. Content-Security-Policy por último, porque é o único dos cinco que exige pensar de verdade e o único que pode impedir os seus próprios scripts de rodar.
Estou no domínio padrão do meu builder e não existe configuração de cabeçalhos. E agora?
Deixe como está. Quando o seu app é servido a partir de um subdomínio da plataforma, os cabeçalhos de resposta são escolha da plataforma e não sua, e não existe arquivo que você possa adicionar para mudá-los. Conecte um domínio próprio se quiser controle sobre isso, porque é o domínio que permite colocar uma hospedagem sua ou um proxy na frente do app. Até lá, gaste o esforço nos achados que cabe a você corrigir.
Uma Content-Security-Policy pode quebrar o meu app?
Pode, e esse é o resultado normal de uma primeira tentativa. Uma política que não permite scripts inline vai parar os scripts inline, inclusive os que o seu builder gerou, e a página fica em branco ou perde uma função, com um erro que só aparece no console do navegador. Comece com Content-Security-Policy-Report-Only, que relata o que teria bloqueado sem bloquear nada, e leia os relatórios por uma semana antes de ligar de verdade.
Cabeçalhos de segurança ajudam se o meu banco de dados pode ser lido por qualquer um?
Não. Cabeçalhos são instruções para os navegadores que visitam o seu site, e quem lê o seu banco de dados direto não está usando navegador nem visitando o seu site. Essa requisição vai direto para o seu provedor de banco de dados e nunca toca nas suas páginas, então nenhum cabeçalho colocado nelas se aplica a ela. Quem decide essa é o Row Level Security.