Gerador de CSP

Passe o endereço de uma página real. Lemos o HTML, listamos todos os lugares de onde ela carrega scripts, estilos, imagens, fontes e frames, e escrevemos uma política que você pode testar no modo report-only, onde ela não quebra nada.

Escolha uma página típica, não só a página inicial: uma página de produto, um artigo, o formulário de contato. Cada uma pode carregar coisas de lugares diferentes.

Ou experimente github.com, wordpress.org, www.bbc.com

Uma lista de convidados para as suas próprias páginas

Um navegador faz o que a página mandar. Se o HTML diz “execute este script daquele servidor”, ele executa. Isso fica perigoso no dia em que outra pessoa consegue acrescentar uma linha à sua página, por um campo de comentário que ninguém limpou, um plugin comprometido ou um anúncio. O navegador não tem como distinguir a linha dela da sua.

Uma Content-Security-Policy (CSP) é um cabeçalho de resposta em que você diz ao navegador, de antemão, de onde esta página pode carregar coisas. Funciona como uma lista de convidados, com uma linha por tipo de recurso:

default-src 'self';
script-src 'self' https://cdn.example.com;
img-src 'self' data: https://images.example.net;
object-src 'none'

Cada linha é uma diretiva. 'self' significa a própria origem da página. Tudo o que não está na lista é recusado, e a recusa fica registrada no console do navegador.

Como esta página monta o rascunho

Nosso servidor busca o endereço uma vez e analisa o HTML como um navegador faria, sem executar nada. Cada endereço encontrado é reduzido à sua origem (esquema e host, sem caminho) e classificado:

DiretivaLida de
script-src<script src>, preloads de módulos e endereços de scripts citados dentro de trechos inline de carregamento
style-srclinks de folhas de estilo e regras @import
img-src, font-srctags de imagem, srcset, ícones, posters, preloads e url() no CSS inline e nas quatro primeiras folhas de estilo da própria origem do site
frame-src, media-src, object-src, manifest-srcframes, áudio e vídeo, plugins, o link do manifesto
form-action, base-uridestinos de formulários e a tag <base>
connect-srcsó as dicas de preconnect e os endpoints documentados de alguns serviços encontrados na página (Google Analytics, Google Fonts, Cloudflare Web Analytics)

O rascunho parte de default-src 'self', acrescenta uma linha por diretiva e fecha as portas que não têm fallback: object-src 'none', base-uri 'self', frame-ancestors 'self', além de upgrade-insecure-requests nas páginas HTTPS. Se a página já envia uma política, num cabeçalho ou numa meta tag, mostramos essa política e a comparamos com o que a página carrega.

A parte difícil: código inline

Código injetado é quase sempre inline, como um bloco <script> ou um atributo onclick escrito na página. Uma política que valha a pena, portanto, proíbe código inline. O problema é que a maioria dos sites tem bastante código inline próprio. A ferramenta conta blocos de script, atributos de manipuladores de eventos, links javascript:, blocos de estilo e atributos style=, depois entrega dois rascunhos.

  • O rascunho estrito não tem 'unsafe-inline'. É onde você quer chegar, e ele quebraria o código inline contado acima.
  • O rascunho de transição acrescenta 'unsafe-inline' onde a página precisa. Ele ainda limita de quais sites as coisas podem ser carregadas, mas não impede mais scripts inline injetados, por isso é marcado como fraco.

Dá para ir de um ao outro de três jeitos. Mover o código para arquivos, fazer o servidor carimbar cada tag com um nonce por resposta, ou listar na política o hash SHA-256 de cada bloco. A ferramenta calcula esses hashes para os blocos de script que encontrou. Eles só servem para blocos cujo texto nunca muda.

Primeiro report-only, sempre

Envie o rascunho como Content-Security-Policy-Report-Only. O navegador não aplica nada e registra o que teria bloqueado. Navegue pelo site com o console aberto, acrescente o que faltar de legítimo e repita até o registro ficar em silêncio. Depois renomeie o cabeçalho para Content-Security-Policy. Você recebe trechos para Apache, nginx e meta tag. A forma meta não permite report-only nem frame-ancestors.

O rascunho vem de uma página, lida uma vez, sem nada executado. Ele não vê as requisições que os scripts fazem depois de carregar (beacons de analytics, widgets de chat, frames de pagamento, imagens com lazy loading), o que os visitantes logados recebem, nem qualquer outra página do site. Conte com acrescentar fontes. Para uma nota dos cabeçalhos que uma página envia hoje, use a nota dos cabeçalhos de segurança.

Perguntas frequentes

Uma Content-Security-Policy vai quebrar meu site?

Uma política aplicada bloqueia tudo o que não lista, então uma política errada vai, sim. Uma política report-only não quebra nada, porque tudo o que ela faz é registrar. Comece por ela e passe para a aplicação quando o console não mostrar nenhuma violação nas suas páginas principais.

Uma política com unsafe-inline vale a pena?

Em parte. Ela ainda restringe para onde scripts, frames e envios de formulário podem ir, bloqueia plugins e impede o sequestro pela tag <base>. Não detém um atacante que consegue escrever um bloco de script na página, e esse é o principal motivo para ter uma política. Use como um passo no caminho.

Qual a diferença entre nonce e hash?

Um nonce é um valor aleatório que o servidor gera a cada resposta e repete em cada tag de script em que confia. Um hash é a impressão digital de um bloco de código específico, listada na política. Nonces combinam com páginas geradas a cada requisição. Hashes combinam com alguns trechos estáticos em páginas que podem ficar em cache.

Por que os caminhos ficam fora da política gerada?

A CSP aceita caminhos como https://cdn.example.com/lib/, mas eles são ignorados depois de um redirecionamento e quebram assim que um arquivo muda de lugar. A maioria das políticas em produção lista origens. Se uma origem hospeda arquivos de muitas partes, como uma CDN pública, fixe também os arquivos exatos com hashes de integridade.

Posso definir uma CSP no WordPress ou em outro CMS?

Sim, pela configuração do servidor web ou por um plugin de segurança que envia cabeçalhos. O tema e os plugins vão trazer uma longa lista de scripts e estilos inline, então comece pelo cabeçalho report-only e pelo rascunho de transição, depois reduza o código inline um plugin por vez.

Onde vejo o que a política bloqueia?

Na guia Console das ferramentas de desenvolvedor do navegador. Cada violação indica a diretiva e o endereço bloqueado. Para coletá-las dos visitantes, acrescente uma diretiva report-uri ou report-to que aponte para um coletor.