Retour au blog
Implémentation20 août 2026Lecture de 10 minMis à jour 30 août 2026

Content Security Policy pour chatbots de site web : autoriser le widget, l'API, les images et le streaming en toute sécurité

Une CSP pratique pour les chatbots de site web autorise uniquement les scripts, connexions API, flux et images réellement nécessaires, sans caractères génériques superflus.

Une technicienne du spectacle adulte vérifie un module de connexion sécurisé pour un widget de chatbot sur une scène extérieure estivale.

Dans le navigateur, un chatbot de site web se résume rarement à un seul fichier JavaScript. Un chargeur ouvre le widget, une API reçoit les messages, les réponses arrivent sous forme de flux et les images de profil ou médias peuvent résider sur un autre domaine. Une politique de sécurité du contenu (CSP) rend ces parcours visibles et les limite : le navigateur ne charge ou ne se connecte qu'à ce que le site web autorise explicitement.

Il s'agit d'une couche de protection secondaire essentielle contre le Cross-Site Scripting et le contenu tiers inattendu. Cependant, une CSP ne répare ni une API non sécurisée, ni une authentification manquante, ni une validation d'entrée défaillante ou une injection de prompt. Elle réduit les possibilités de code injecté et limite le rayon d'impact d'une erreur. Il est donc crucial d'avoir une politique la plus restreinte et testée possible plutôt qu'une longue liste de domaines autorisés globalement.

Pourquoi les widgets de chatbot nécessitent des règles CSP spécifiques

Sur une page de contenu classique, les ressources provenant de l'origine propre suffisent souvent. En revanche, un chatbot continue de communiquer après son chargement. connect-src contrôle notamment fetch(), XMLHttpRequest, EventSource, WebSocket et sendBeacon(). C'est précisément là que circulent les messages, les réponses en streaming, les événements de retour d'information et, le cas échéant, la télémétrie. Si l'origine correcte manque, le widget s'affiche mais ne peut pas répondre.

D'autres composants relèvent de directives distinctes. script-src régit le chargeur de widget, img-src régit les avatars et images de réponse, style-src régit les feuilles de style et font-src régit les polices externes. Un widget basé sur un iframe a également besoin de frame-src. default-src sert de repli pour de nombreux types de ressources non nommés explicitement, mais ne remplace pas un inventaire délibéré.

Le travail préparatoire le plus important ne se fait donc pas dans le générateur CSP, mais dans le navigateur : ouvrez une page représentative, démarrez une conversation, laissez une réponse longue se diffuser, ouvrez des sources, envoyez du feedback et testez les cas d'erreur et de transfert à un humain. Dans le panneau Réseau, vous verrez les origines réellement sollicitées. Documentez l'objectif, le type de ressource et le responsable pour chaque hôte.

Autoriser séparément les quatre voies de données pertinentes

1. Script de widget et initialisation

Obtenez le chargeur si possible à partir d'une adresse stable et versionnée. Une autorisation telle que script-src https: serait trop large, car elle rendrait admissibles les scripts de n'importe quel domaine HTTPS. Autorisez plutôt l'origine exacte du CDN ou hébergez vous-même le chargeur. Si l'intégration nécessite du code en ligne (inline), utilisez un nonce généré à chaque réponse HTTP ou un hachage approprié. 'unsafe-inline' ne doit pas devenir une solution permanente de facilité.

Un nonce n'appartient qu'aux scripts générés par le modèle côté serveur lui-même. Un middleware qui ajouterait aveuglément le même nonce à chaque balise de script existante ferait également confiance aux balises injectées. Pour un script tiers statique et versionné, l'intégrité des sous-ressources (SRI) peut aider ; pour les fichiers qui changent fréquemment, le hachage doit toutefois être mis à jour de manière contrôlée.

2. API, Server-Sent Events et WebSocket

Les requêtes POST normales et une réponse diffusée en continu via fetch() nécessitent l'origine API HTTPS dans connect-src. Les Server-Sent Events via EventSource relèvent également de cette directive. Pour un WebSocket, inscrivez explicitement l'origine wss:// concrète. MDN souligne que 'self' n'inclut pas automatiquement les schémas WebSocket dans tous les navigateurs. Il n'existe pas de directive propre nommée stream-src.

La CSP et le CORS résolvent des problèmes différents. La CSP détermine où la page a le droit de se connecter ; le CORS détermine côté serveur quelles origines peuvent lire une réponse dans le navigateur. Une autorisation CSP ne résout donc ni une erreur CORS ni un jeton d'accès expiré. Un proxy same-origin peut simplifier la politique, mais il doit toujours gérer correctement l'authentification, les limites de débit, les délais d'expiration et la transmission des erreurs.

3. Images, avatars et médias générés

Dans img-src, n'autorisez que votre propre origine et l'origine média réellement utilisée. data: n'est nécessaire que si le widget utilise de petites images intégrées ; blob: uniquement si le navigateur génère réellement des images sous forme d'URL Blob. Chaque source supplémentaire augmente la surface d'attaque. Si une image est d'abord chargée via fetch() puis convertie en URL Blob, connect-src et img-src peuvent être concernés tous les deux.

Ne testez pas seulement l'avatar par défaut. Vérifiez les images d'aperçu, les captures d'écran des sources, les pièces jointes, le mode sombre et l'affichage des erreurs pour les médias indisponibles. Les paramètres d'URL peuvent transporter des informations confidentielles dans les rapports CSP ; les points de terminaison de rapport doivent donc traiter les rapports de manière sobre et ne pas les conserver indéfiniment.

4. iframe, styles, polices et workers optionnels

Un widget directement intégré dans le DOM n'a généralement pas besoin de cadre externe. frame-src 'none' peut alors être conservé. En revanche, si le chat s'exécute dans un iframe, autorisez exclusivement son origine exacte. Il convient de distinguer cette directive de frame-ancestors : cette dernière définit sur la ressource fournie quelles pages sont autorisées à l'intégrer. Le fournisseur du widget doit donc la définir correctement sur sa réponse iframe.

Le même principe s'applique aux styles et aux polices. Autorisez des hôtes concrets et évitez 'unsafe-inline', dans la mesure où l'intégration le permet. Les workers ou fonctionnalités audio ne s'ajoutent que si le produit les utilise réellement. Une autorisation préventive de blob:, de domaines génériques entiers ou de n'importe quelle source média complique les audits ultérieurs.

Un exemple CSP réaliste pour un widget de chatbot

Les domaines suivants sont délibérément des domaines d'exemple réservés. Remplacez-les par les origines issues de votre propre analyse réseau. L'exemple suppose un chargeur externe, une API HTTPS, un WebSocket séparé pour le streaming et un hôte média. Il n'utilise aucun caractère générique global :

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;

{RANDOM} représente une valeur forte, régénérée à chaque réponse, identique dans l'en-tête et sur les éléments script ou style autorisés. Si votre widget utilise un iframe, remplacez frame-src 'none' par l'origine exacte du widget. S'il utilise exclusivement le streaming HTTPS via fetch() ou EventSource, l'origine WebSocket est inutile. Supprimez toute source qui n'est pas nécessaire après un test fonctionnel complet.

La politique est un point de départ pratique, pas un modèle universel. Une CSP stricte moderne peut contrôler les scripts encore plus fortement via des nonces ou des hachages et 'strict-dynamic'. La possibilité de le faire sans problème de compatibilité dépend de la façon dont le chargeur génère d'autres scripts. Clarifiez ce processus avec le fournisseur et testez les navigateurs, le mode de consentement et les variantes de déploiement.

Du mode Report-Only à la politique appliquée

Ne passez pas une nouvelle politique en production sans vérification. Le mécanisme W3C Content-Security-Policy-Report-Only signale les violations sans bloquer les ressources. Cela vous permet d'identifier les hôtes d'images oubliés, une origine de streaming divergente ou du code en ligne avant que les utilisateurs ne soient impactés. OWASP recommande l'en-tête HTTP comme moyen de diffusion privilégié ; contrairement à l'élément meta, il prend en charge l'ensemble des fonctionnalités.

  1. Créer un inventaire : Testez le démarrage du widget, le premier message, une réponse longue en streaming, les sources, les images, le feedback, le transfert et les changements de consentement sur plusieurs types de pages.
  2. Déployer le mode Report-Only : Commencez par la politique restreinte prévue et collectez les violations pendant une période limitée. Filtrez les extensions de navigateur et autres signaux parasites non reproductibles.
  3. Justifier chaque hôte : N'élargissez la politique que si une fonction produit concrète nécessite l'origine. Évitez les caractères génériques en réaction à des rapports isolés.
  4. Tester de manière automatisée : Ajoutez des tests de bout en bout qui envoient un message, attendent le streaming et chargent une image. Vérifiez simultanément la console du navigateur pour détecter les violations CSP.
  5. Appliquer et observer : Activez l'en-tête Content-Security-Policy, gardez un œil en parallèle sur une variante Report-Only encore plus stricte et comparez les taux d'erreur.

Un déploiement progressif s'adapte très bien à un chatbot en Shadow Mode. Pour des métriques spécifiques au streaming, vous pouvez consulter l'article sur les budgets de latence et les timeouts. Les violations CSP doivent alors être considérées comme un signal distinct : un timeout et une connexion bloquée nécessitent des analyses de cause racine différentes.

Erreurs de configuration fréquentes

  • Listes de sources trop larges : *, https: ou de grands domaines génériques rendent la politique pratique, mais faible et difficile à vérifier.
  • Seul le démarrage visible est testé : Le widget s'ouvre, mais le streaming, le feedback, les images ou le transfert échouent plus tard.
  • 'unsafe-inline' reste en permanence : Une aide à la compatibilité à court terme n'est pas remplacée par des nonces, des hachages ou du code externe.
  • Confondre CSP et contrôle d'accès : La politique ne remplace ni les droits côté serveur, ni la vérification de session, ni la protection contre les appels d'outils abusifs.
  • Les rapports contiennent trop de données : Des URL complètes, des paramètres de requête ou du contexte utilisateur se retrouvent inutilement longtemps dans le système de surveillance.
  • Décalage entre Staging et Production : Des hôtes CDN, API ou WebSocket différents n'apparaissent qu'après la mise en ligne.

Même un script-src restreint ne rend pas automatiquement un tiers autorisé sécurisé : son JavaScript s'exécute avec les possibilités que votre page lui donne. Vérifiez donc les changements de fournisseur, les nouveaux sous-domaines et les mises à jour de chargeur comme n'importe quelle autre dépendance critique pour la sécurité. L'article sur la protection contre l'injection de prompt complète cette frontière du navigateur avec des règles pour le RAG, les outils et les données.

Check-list avant la mise en ligne

  • Toutes les origines requises sont-elles documentées à partir de sessions de navigateur réelles et justifiées sur le plan fonctionnel ?
  • script-src n'autorise-t-il que le chargeur et les scripts contrôlés, sans 'unsafe-inline' global ?
  • connect-src contient-il les origines exactes HTTPS, EventSource et, le cas échéant, WSS ?
  • Les sources d'images, de styles, de polices, de frames et de workers sont-elles séparées et définies aussi étroitement que possible ?
  • Les nonces sont-ils générés à chaque réponse et appliqués uniquement aux éléments de confiance ?
  • Les changements de consentement, les flux longs, les images, les erreurs, les transferts ainsi que les appareils de bureau et mobiles ont-ils été testés ?
  • La politique a-t-elle d'abord été observée en mode Report-Only puis appliquée via un en-tête ?
  • Les rapports CSP sont-ils traités sans données personnelles ou confidentielles superflues dans les URL ?
  • Existe-t-il un test de régression automatisé après les mises à jour du widget ou de l'infrastructure ?

Conclusion

Une bonne CSP pour les chatbots de site web n'est pas une collection d'exceptions, mais une carte géographique technique des parcours autorisés dans le navigateur. Séparez le chargeur, l'API, le streaming, les images et les ressources iframe, autorisez les origines exactes et introduisez d'abord la politique en mode Report-Only. De cette façon, le widget reste fonctionnel tout en laissant nettement moins de marge de manœuvre aux scripts et connexions inattendus.

Sources

Transformez les visites en conversations de qualité

Lancez un chatbot IA utile dès le premier jour

Entraînez ChatReact avec votre site, vos documents et des faits approuvés pour que les visiteurs obtiennent des réponses plus rapides et que votre équipe reçoive moins de demandes répétitives.

Articles associés

Continuer la lecture