Voltar ao blog
Implementação20 de agosto de 2026Leitura de 10 minAtualizado em 30 de agosto de 2026

Content Security Policy para Chatbots de Website: Permita Widget, API, Imagens e Streaming com Segurança

Uma CSP prática para chatbots de website permite apenas os scripts, conexões de API, streams e imagens estritamente necessários — sem wildcards desnecessários.

Uma técnica de eventos adulta inspeciona um módulo de conexão protegido para um widget de chatbot em um palco ao ar livre no verão.

Um chatbot de website raramente consiste em apenas um único arquivo JavaScript no navegador. Um loader abre o widget, uma API recebe mensagens, as respostas retornam como uma transmissão contínua (stream) e fotos de perfil ou mídias podem estar hospedadas em outro domínio. Uma Content Security Policy (CSP) torna esses caminhos visíveis e os limita: o navegador só carrega ou se conecta ao que o site permite explicitamente.

Essa é uma segunda camada de proteção essencial contra Cross-Site Scripting (XSS) e conteúdos de terceiros inesperados. No entanto, uma CSP não corrige uma API insegura, falta de autenticação, validação de entrada deficiente ou Prompt Injection. Ela reduz as possibilidades de código injetado e limita o raio de alcance de uma falha. Por isso, o fator decisivo é ter uma política a mais enxuta e testada possível, em vez de uma longa lista de domínios liberados de forma genérica.

Por que widgets de chatbot precisam de regras de CSP especiais

Em uma página de conteúdo clássica, recursos da própria origem geralmente são suficientes. Já um chatbot continua se comunicando continuamente após o carregamento inicial. A diretiva connect-src controla, entre outros, fetch(), XMLHttpRequest, EventSource, WebSocket e sendBeacon(). É exatamente aqui que trafegam mensagens, respostas via streaming, eventos de feedback e, eventualmente, dados de telemetria. Se a origem correta estiver ausente, o widget até será exibido, mas não conseguirá responder.

Outros componentes ficam sob a responsabilidade de diretivas específicas. O script-src decide sobre o loader do widget, img-src sobre avatares e imagens das respostas, style-src sobre folhas de estilo e font-src sobre fontes externas. Um widget baseado em iframe precisa, além disso, de frame-src. O default-src serve como um plano de reserva (fallback) para vários tipos de recursos não nomeados explicitamente, mas não substitui um levantamento consciente das necessidades.

Portanto, o trabalho prévio mais importante não acontece no gerador de CSP, mas no próprio navegador: abra uma página representativa, inicie uma conversa, faça uma resposta longa ser transmitida via streaming, abra fontes citadas, envie feedback e teste cenários de erro e de transferência para atendimento humano (handoff). No painel de rede (Network tab), você verá as origens realmente acionadas. Documente para cada host a sua finalidade, o tipo de recurso e uma pessoa responsável.

Liberando os quatro caminhos de dados relevantes separadamente

1. Script do widget e inicialização

Obtenha o loader, se possível, de um endereço estável e versionado. Liberar algo como script-src https: seria amplo demais, pois tornaria válidos scripts de qualquer domínio HTTPS. Em vez disso, permita a origem exata da CDN ou sirva o loader a partir do seu próprio servidor. Se a integração exigir código inline, use um nonce gerado do zero para cada resposta HTTP ou um hash apropriado. O uso de 'unsafe-inline' não deve se tornar uma solução permanente e rápida.

Um nonce deve ser atribuído apenas aos scripts que o próprio template no lado do servidor gera. Um middleware que adicione cegamente o mesmo nonce a qualquer tag de script existente também daria confiança a tags injetadas por invasores. Para um script externo estático e versionado, a Subresource Integrity (SRI) pode ajudar adicionalmente; porém, em arquivos que mudam com frequência, o hash precisa ser atualizado de forma controlada.

2. API, Server-Sent Events e WebSocket

Requisições POST normais e uma resposta transmitida via fetch() exigem a origem da API HTTPS em connect-src. Server-Sent Events via EventSource também se enquadram nessa regra. Para um WebSocket, inclua explicitamente a origem wss:// concreta. A MDN aponta que o valor 'self' não abrange automaticamente esquemas WebSocket em todos os navegadores. Não existe uma diretiva própria chamada stream-src.

CSP e CORS resolvem problemas distintos. A CSP determina para onde a página pode se conectar; o CORS estabelece, no lado do servidor, quais origens têm permissão para ler uma resposta no navegador. Portanto, uma liberação na CSP não resolve um erro de CORS nem um token de acesso expirado. Um proxy de mesma origem (same-origin proxy) pode simplificar a política, mas ainda precisa lidar corretamente com autenticação, limites de taxa (rate limits), tempos limite (timeouts) e repasse de erros.

3. Imagens, avatares e mídias geradas

Em img-src, permita apenas a sua própria origem e a origem de mídia que é realmente utilizada. O uso de data: só é necessário se o widget utilizar pequenas imagens incorporadas; e blob: apenas se o navegador gerar imagens como URLs Blob. Cada fonte adicional aumenta a superfície de ataque. Se uma imagem for carregada primeiro via fetch() e depois convertida em uma URL Blob, tanto connect-src quanto img-src podem ser afetados.

Não teste apenas o avatar padrão. Verifique imagens de pré-visualização, capturas de tela de fontes, anexos de arquivos, modo escuro e a exibição de erros para mídias indisponíveis. Parâmetros de URL podem carregar informações confidenciais para os relatórios de CSP; por isso, os endpoints de relatório devem processar dados com parcimônia e não armazená-los indefinidamente.

4. iframe, estilos, fontes e workers opcionais

Um widget embutido diretamente no DOM geralmente não precisa de um frame externo. Nesses casos, frame-src 'none' pode ser mantido. Se, por outro lado, o chat roda dentro de um iframe, permita exclusivamente a sua origem exata. Isso difere de frame-ancestors: essa diretiva define, no recurso servido, quais páginas têm permissão para incorporá-lo. Portanto, o provedor do widget precisa configurá-la adequadamente na resposta do seu iframe.

Para estilos e fontes, aplica-se o mesmo princípio. Permita hosts concretos e evite 'unsafe-inline', à medida que a integração permitir. Workers ou recursos de áudio só devem ser adicionados se o produto realmente os utilizar. Liberar preventivamente blob:, domínios com wildcard genéricos ou fontes de mídia arbitrárias dificulta auditorias futuras.

Um exemplo realista de CSP para um widget de chatbot

Os domínios a seguir são propositalmente domínios de exemplo reservados. Substitua-os pelas origens identificadas na sua própria análise de rede. O exemplo pressupõe um loader externo, uma API HTTPS, um WebSocket separado para streaming e um host de mídia. Ele não utiliza wildcards genéricos:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.chat.example 'nonce-{RANDOM}';
  connect-src 'self' https://api.chat.example wss://stream.chat.example;
  img-src 'self' data: https://media.chat.example;
  style-src 'self' 'nonce-{RANDOM}';
  font-src 'self';
  frame-src 'none';
  worker-src 'self';
  object-src 'none';
  base-uri 'self';
  frame-ancestors 'self';
  form-action 'self';
  upgrade-insecure-requests;

O termo {RANDOM} representa um valor forte, gerado do zero para cada resposta, que deve ser idêntico no cabeçalho e nos elementos de script ou estilo permitidos. Se o seu widget utiliza um iframe, substitua frame-src 'none' pela origem exata do widget. Se ele utiliza exclusivamente streaming HTTPS via fetch() ou EventSource, a origem do WebSocket pode ser omitida. Remova qualquer fonte que não seja necessária após um teste funcional completo.

Esta política é um ponto de partida prático, não um modelo universal. Uma CSP estrita e moderna pode controlar scripts de forma ainda mais rígida por meio de nonces ou hashes e 'strict-dynamic'. Se isso é possível sem problemas de compatibilidade, depende de como o loader cria scripts adicionais. Esclareça esse fluxo com o provedor e teste navegadores, modo de consentimento (Consent Mode) e variações de implantação.

Do modo Report-Only à política aplicada (enforced)

Não ative uma nova política em produção sem antes testá-la. O mecanismo Content-Security-Policy-Report-Only do W3C notifica violações sem bloquear recursos. Dessa forma, você identifica hosts de imagens esquecidos, uma origem de streaming divergente ou código inline antes que os usuários sejam afetados. O OWASP recomenda o cabeçalho HTTP como a via de entrega preferencial; ao contrário do elemento meta, ele oferece suporte a todo o conjunto de funcionalidades.

  1. Criar um inventário: Teste a inicialização do widget, a primeira mensagem, respostas longas em streaming, fontes, imagens, feedback, handoff e alterações de consentimento em vários tipos de páginas.
  2. Implantar em Report-Only: Comece com a política restrita planejada e colete violações durante um período definido. Filtre extensões de navegador e outros ruídos não reproduzíveis.
  3. Justificar cada host: Amplie a política apenas se uma funcionalidade concreta do produto exigir a origem. Evite usar wildcards como reação a relatórios isolados.
  4. Testar de forma automatizada: Adicione testes de ponta a ponta (E2E) que enviem uma mensagem, aguardem o streaming e carreguem uma imagem. Ao mesmo tempo, verifique o console do navegador em busca de violações de CSP.
  5. Aplicar e monitorar: Ative o cabeçalho Content-Security-Policy, mantenha uma variante Report-Only ainda mais rigorosa sob observação paralela e compare as taxas de erro.

Uma implantação em fases combina perfeitamente com um chatbot em Shadow Mode. Para métricas específicas de streaming, consulte nosso artigo sobre orçamentos de latência e timeouts. Violações de CSP devem ser tratadas como um sinal próprio: um timeout e uma conexão bloqueada exigem análises de causa raiz diferentes.

Erros comuns de configuração

  • Listas de fontes genéricas demais: *, https: ou grandes domínios com wildcard tornam a política conveniente, porém fraca e difícil de auditar.
  • Testar apenas o início visível: O widget abre corretamente, mas o streaming, o feedback, as imagens ou o handoff falham mais tarde.
  • Manter 'unsafe-inline' permanentemente: Uma solução temporária de compatibilidade deixa de ser substituída por nonces, hashes ou código externo.
  • Confundir CSP com controle de acesso: A política não substitui permissões no lado do servidor, checagem de sessão ou proteção contra chamadas abusivas de ferramentas.
  • Relatórios contendo dados em excesso: URLs completas, parâmetros de consulta (query) ou contexto do usuário terminam armazenados no monitoramento por tempo desnecessário.
  • Divergência entre staging e produção: Hosts de CDN, API ou WebSocket diferentes só se tornam visíveis após o go-live.

Mesmo um script-src restrito não torna um terceiro permitido automaticamente seguro: o JavaScript dele é executado com todas as capacidades que a sua página concede a ele. Portanto, verifique trocas de fornecedores, novos subdomínios e atualizações de loaders como faria com qualquer outra dependência crítica de segurança. O artigo sobre proteção contra Prompt Injection complementa essa barreira do navegador com regras para RAG, ferramentas e dados.

Lista de verificação antes do go-live

  • Todas as origens necessárias foram documentadas a partir de sessões reais do navegador e justificadas tecnicamente?
  • O script-src permite apenas o loader e scripts controlados, sem o uso genérico de 'unsafe-inline'?
  • O connect-src contém as origens exatas de HTTPS, EventSource e, se aplicável, WSS?
  • As fontes de imagem, estilo, fonte, frame e worker estão separadas e definidas da forma mais estrita possível?
  • Os nonces são gerados novamente a cada resposta e atribuídos apenas a elementos confiáveis?
  • Foram testadas mudanças de consentimento, streams longos, imagens, erros, handoff, bem como dispositivos desktop e móveis?
  • A política foi observada primeiro em modo Report-Only e depois aplicada como cabeçalho obrigatório?
  • Os relatórios de CSP são processados sem dados pessoais ou URLs confidenciais desnecessárias?
  • Existe um teste de regressão automatizado após atualizações do widget ou da infraestrutura?

Conclusão

Uma boa CSP para chatbots de website não é uma coleção de exceções, mas um mapa técnico dos caminhos permitidos no navegador. Separe o loader, a API, o streaming, as imagens e os recursos de iframe, permita origens exatas e implemente a política primeiro no modo Report-Only. Dessa forma, o widget permanece totalmente funcional, enquanto scripts e conexões inesperadas ganham muito menos margem para agir.

Fontes

Transforme visitas ao site em conversas melhores

Lance um chatbot de IA útil desde o primeiro dia

Treine o ChatReact com seu site, documentos e fatos aprovados para que os visitantes obtenham respostas mais rápidas e sua equipe receba menos pedidos repetitivos.

Artigos relacionados

Continuar lendo