Tous les articles

Plusieurs politiques CSP sur une même page

CentralCSP Team ·

Dernière mise à jour:

Vous pouvez envoyer plusieurs politiques de sécurité du contenu (CSP) à une même page, et le navigateur va toutes les respecter en même temps. Une CSP est un header de réponse HTTP qui indique au navigateur quels scripts, styles et autres ressources une page a le droit de charger. Quand une page en porte plusieurs, le navigateur ne les fusionne pas en une seule politique. Il vérifie chacune indépendamment, et une ressource doit passer toutes les politiques pour se charger.

Cette seule règle explique presque tout sur les politiques multiples : ajouter une politique ne peut que rendre une page plus stricte, jamais plus permissive. Un deuxième header ne peut pas réautoriser ce que le premier a bloqué. Cet article montre comment les politiques se combinent, les pièges qui surprennent, et comment tester une politique plus stricte en toute sécurité avant de l'appliquer.

Comment un navigateur combine plusieurs politiques

Une page peut récupérer des politiques depuis plusieurs sources en même temps :

  • Plusieurs headers de réponse HTTP Content-Security-Policy.
  • Un seul header Content-Security-Policy qui contient plusieurs politiques séparées par des virgules. Chaque segment séparé par une virgule compte comme une politique à part entière.
  • Un élément <meta http-equiv="Content-Security-Policy">, appliqué en plus des headers.
  • Un ou plusieurs headers Content-Security-Policy-Report-Only, qui signalent les violations mais ne bloquent jamais.

Le navigateur rassemble toutes les politiques actives dans une seule liste et les évalue indépendamment. Pour une requête donnée, il part de l'état « autorisé », puis parcourt la liste. Si une politique appliquée est violée, la requête est bloquée, et rien plus loin dans la liste ne peut la repasser à « autorisé ». C'est le mécanisme derrière la formule que vous entendrez souvent, « la politique la plus restrictive l'emporte ».

Les politiques Report-Only sont ignorées lors de cette décision de blocage. Elles ne sont évaluées que pour produire des reports, donc elles influencent ce que vous voyez dans votre monitoring, pas ce que le navigateur charge réellement.

Une ressource doit satisfaire chaque politique

Voici l'exemple canonique, deux headers Content-Security-Policy sur la même réponse :

Content-Security-Policy: default-src 'self' http://example.com;
                         connect-src 'none';
Content-Security-Policy: connect-src http://example.com/;
                         script-src http://example.com/

Le deuxième header indique connect-src http://example.com/, donc à lui seul il autoriserait cette connexion. Cela n'a aucune importance. La première politique fixe connect-src 'none', et la requête doit passer les deux. Comme une politique interdit toutes les connexions, la connexion est bloquée, et la règle effective pour connect-src est 'none'.

MDN décrit la combinaison de la même manière : ajouter des politiques « ne peut que restreindre davantage les capacités de la ressource protégée ». Il n'y a aucun moyen d'écrire une deuxième politique qui assouplit la première.

L'ordre des headers ne change pas le résultat. Que connect-src 'none' arrive en premier ou en second, le résultat est identique, parce que chaque politique est vérifiée indépendamment et que la requête doit toutes les franchir.

Le piège de l'intersection avec les allowlists d'hôtes

La règle « passer chaque politique » a un effet de bord tranchant quand deux politiques autorisent des ensembles d'hôtes qui se recoupent mais diffèrent. On s'attend à ce que le navigateur prenne l'union des hôtes. Il fait l'inverse.

Content-Security-Policy: script-src 'self' https://trusted.com https://analytics.com
Content-Security-Policy: script-src 'self' https://trusted.com

Un script depuis https://analytics.com passe la première politique mais échoue à la deuxième, donc il est bloqué. Un script depuis https://trusted.com passe les deux, donc il se charge. Le résultat effectif est l'intersection des deux allowlists, 'self' et https://trusted.com, parce qu'une ressource doit satisfaire chaque politique individuellement.

C'est facile à provoquer par accident. Si une équipe ajoute une CSP au niveau du CDN ou du proxy et qu'une autre en ajoute une dans l'application, un hôte que seule l'une des deux autorise se retrouve bloqué. Quand une ressource est autorisée par une politique mais pas par l'autre, elle ne se charge pas, point final. Si vous déboguez une ressource qui « devrait » être autorisée, vérifiez si une deuxième politique est en jeu avant de toucher à la directive que vous examiniez.

Le fallback default-src est résolu à l'intérieur de chaque politique séparément, avant que la vérification entre politiques ne s'applique. Le navigateur ne construit jamais une politique fusionnée unique, donc le fallback d'une directive dans la politique A n'a aucun effet sur la politique B.

Pour une page qui a besoin d'une politique claire et maintenable, préférez tout consolider dans un seul header bien structuré plutôt que de disperser les directives sur plusieurs. Notre évaluateur CSP signale les directives faibles ou contradictoires pour que vous voyiez la vraie politique effective avant de la déployer.

Tester une politique plus stricte sans casser la page

La raison la plus utile de faire tourner plusieurs politiques, c'est d'appliquer ce qui fonctionne aujourd'hui tout en testant quelque chose de plus serré. Vous appliquez une politique et faites tourner la plus stricte en Report-Only en même temps :

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'

Les scripts depuis https://trusted.com se chargent toujours, parce que la politique appliquée les autorise. La politique Report-Only est plus stricte, donc le navigateur envoie aussi un report de violation pour chacun de ces scripts, sans rien bloquer. Vous lisez ces reports, confirmez que la politique plus stricte ne casserait pas la page, puis vous la promouvez dans le header appliqué.

Pour collecter les reports, pointez la politique vers un endpoint de reporting. Envoyez un header Reporting-Endpoints et référencez-le depuis la directive report-to dans chaque politique :

Reporting-Endpoints: csp-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com; report-to csp-endpoint
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; report-to csp-endpoint

Une chose à anticiper : chaque politique appliquée qu'une requête viole émet son propre report. Si vous faites tourner plusieurs politiques et qu'une seule ressource bloquée en viole deux, vous obtenez deux reports pour ce seul blocage. C'est attendu, puisque le navigateur signale par politique, mais cela signifie que votre volume brut de reports croît avec le nombre de politiques, pas avec le nombre de problèmes distincts. Regrouper les reports par ressource et par directive, plutôt que de compter les événements bruts, limite le bruit. C'est le genre de corrélation que CentralCSP fait pour vous, pour que l'essai en Report-Only se lise comme une courte liste de changements à faire, et non comme un flot d'événements en double.

Ce qu'il faut retenir

  • Plusieurs politiques sont appliquées indépendamment. Une ressource doit toutes les passer pour se charger.
  • Une politique supplémentaire ne peut qu'ajouter des restrictions. Elle ne peut jamais réautoriser ce qu'une autre politique a bloqué.
  • Les allowlists d'hôtes qui se recoupent s'intersectent. Un hôte autorisé par une seule politique reste bloqué.
  • L'ordre des headers n'a pas d'importance.
  • Report-Only ne bloque jamais, c'est donc le moyen sûr de tester une politique plus stricte à côté d'une politique qui fonctionne.
  • Une seule ressource bloquée peut produire un report par politique violée.

Ce comportement fait partie de CSP Level 3 et fonctionne dans tout navigateur qui prend en charge CSP. Si vous voulez prendre de l'avance, vous pouvez scanner votre configuration actuelle avec le scanner CSP gratuit et voir comment vos politiques se combinent avant de changer quoi que ce soit.

Pour en savoir plus sur les briques de base derrière ces exemples, voir comment construire une CSP solide et démarrer avec le reporting CSP.

Articles liés