Cet article de blog explique comment implémenter la compatibilité des outils pour les développeurs avec le débogage des problèmes liés aux règles de sécurité du contenu (CSP) à l'aide de l'onglet Problèmes récemment introduit.
Le travail d'implémentation a été effectué dans le cadre de deux stages : 1. Lors de la première, nous avons créé le framework de création de rapports général et conçu les messages de problème pour trois cas de non-respect du CSP. 2. Lors de la seconde, nous avons ajouté des problèmes de type approuvé ainsi que certaines fonctionnalités DevTools spécialisées pour le débogage des types approuvés.
Qu'est-ce qu'une stratégie de sécurité du contenu ?
Content Security Policy (CSP) permet de restreindre certains comportements sur un site Web pour renforcer sa sécurité. Par exemple, la CSP peut être utilisée pour interdire les scripts intégrés ou eval
, ce qui réduit la surface d'attaque pour les attaques XSS (Cross-Site Scripting). Pour une présentation détaillée de CSP, cliquez ici.
La règle TT(Trusted Types) est un fournisseur de services de communication particulièrement récent. Elle permet d'effectuer une analyse dynamique capable d'empêcher systématiquement un grand nombre d'attaques par injection sur les sites Web. Pour ce faire, TT aide un site Web à contrôler son code JavaScript afin de n'autoriser que certains types d'éléments à être attribués à des puits DOM tels que innerHTML.
Un site Web peut activer une stratégie de sécurité du contenu en incluant un en-tête HTTP particulier. Par exemple, l'en-tête content-security-policy: require-trusted-types-for 'script'; trusted-types default
active la stratégie TT pour une page.
Chaque stratégie peut fonctionner dans l'un des modes suivants:
- mode d'application : chaque non-respect des règles est une erreur.
- Mode "report-only" (mode "signaler uniquement") : le message d'erreur est signalé en tant qu'avertissement, mais ne provoque pas d'échec sur la page Web.
Implémentation des problèmes liés à Content Security Policy dans l'onglet Issues (Problèmes)
L'objectif de ce travail était d'améliorer l'expérience de débogage pour les problèmes CSP. Lorsqu'elle étudie de nouveaux problèmes, l'équipe DevTools suit à peu près la procédure suivante:
- Définir des histoires d'utilisateurs Identifiez un ensemble d'histoires d'utilisateurs dans le front-end des outils de développement qui explique comment un développeur Web doit examiner le problème.
- Implémentation du front-end Sur la base des histoires d'utilisateurs, identifiez les informations requises pour examiner le problème dans le front-end (par exemple, une requête associée, le nom d'un cookie, une ligne dans un script ou un fichier HTML, etc.).
- Détection des problèmes Identifiez les emplacements du navigateur où le problème peut être détecté dans Chrome et instrumentez-les pour signaler un problème, en incluant les informations pertinentes de l'étape 2.
- Enregistrez et affichez les problèmes. Stockez les problèmes dans un emplacement approprié et mettez-les à la disposition des outils de développement une fois qu'ils sont ouverts.
- Conception du texte des problèmes Imaginez un texte explicatif qui aide le développeur Web à comprendre et, plus important encore, à résoudre le problème.
Étape 1: Définir des histoires d'utilisateurs pour les problèmes liés aux CSP
Avant de commencer notre travail d'implémentation, nous avons créé un document de conception avec des histoires d'utilisateurs pour mieux comprendre ce que nous devions faire. Par exemple, nous avons rédigé l'histoire d'utilisateur suivante:
En tant que développeur, qui vient de réaliser qu'une partie de mon site Web est bloquée, je souhaite:- - ...découvrir si CSP est une raison pour laquelle les iFrame / images sont bloquées sur mon site Web ; - ... identifier la directive CSP qui entraîne le blocage d'une ressource donnée. - ... savoir comment modifier la CSP de mon site Web pour autoriser l'affichage des ressources actuellement bloquées / l'exécution du code JavaScript actuellement bloqué.
Pour explorer cette histoire d'utilisateur, nous avons créé des exemples de pages Web simples qui présentaient les cas de non-respect des règles CSP qui nous intéressaient. Nous avons ensuite exploré ces exemples de pages pour nous familiariser avec le processus. Voici quelques exemples de pages Web (ouvrez la démonstration en laissant l'onglet Problèmes ouvert):
- Problèmes liés aux CSP
- Non-respect de Trusted Types
- Non-respect des Trusted Types – mode Signaler uniquement
Grâce à ce processus, nous avons appris que l'emplacement de la source était l'information la plus importante pour déboguer les problèmes liés aux FSC. Nous avons également trouvé utile de trouver rapidement l'iframe et la requête associée en cas de blocage d'une ressource. Un lien direct vers l'élément HTML dans le panneau Éléments de DevTools pourrait également être utile.
Étape 2: Implémentation du front-end
Nous avons transformé cette information en première ébauche des informations que nous souhaitions mettre à la disposition de DevTools via le protocole Chrome DevTools (CDP):
Vous trouverez ci-dessous un extrait de third_party/blink/public/devtools_protocol/browser_protocol.pdl.
type ContentSecurityPolicyIssueDetails extends object
properties
# The url not included in allowed sources.
optional string blockedURL
# Specific directive that is violated, causing the CSP issue.
string violatedDirective
boolean isReportOnly
ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
optional AffectedFrame frameAncestor
optional SourceCodeLocation sourceCodeLocation
optional DOM.BackendNodeId violatingNodeId
La définition ci-dessus encode essentiellement une structure de données JSON. Il est écrit dans un langage simple appelé PDL (Protocol Data Language). Le PDL est utilisé à deux fins. Tout d'abord, nous utilisons PDL pour générer les définitions TypeScript sur lesquelles le front-end DevTools s'appuie. Par exemple, la définition PDL ci-dessus génère l'interface TypeScript suivante:
export interface ContentSecurityPolicyIssueDetails {
/**
* The url not included in allowed sources.
*/
blockedURL?: string;
/**
* Specific directive that is violated, causing the CSP issue.
*/
violatedDirective: string;
isReportOnly: boolean;
contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
frameAncestor?: AffectedFrame;
sourceCodeLocation?: SourceCodeLocation;
violatingNodeId?: DOM.BackendNodeId;
}
Deuxièmement, et probablement plus important encore, nous générons une bibliothèque C++ à partir de la définition qui gère la génération et l'envoi de ces structures de données du backend Chromium C++ vers le frontend DevTools. À l'aide de cette bibliothèque, vous pouvez créer un objet ContentSecurityPolicyIssueDetails
à l'aide du code C++ suivant:
protocol::Audits::ContentSecurityPolicyIssueDetails::create()
.setViolatedDirective(d->violated_directive)
.setIsReportOnly(d->is_report_only)
.setContentSecurityPolicyViolationType(BuildViolationType(
d->content_security_policy_violation_type)))
.build();
Une fois que nous avons déterminé les informations que nous souhaitions mettre à disposition, nous avons dû déterminer où les trouver dans Chromium.
Étape 3: Détection des problèmes
Pour mettre les informations à la disposition du protocole Chrome DevTools (CDP) au format décrit dans la dernière section, nous avons dû trouver l'emplacement où elles étaient réellement disponibles dans le backend. Heureusement, le code du CSP comportait déjà un goulot d'étranglement utilisé pour le mode "Rapport uniquement", auquel nous pouvions nous connecter: ContentSecurityPolicy::ReportViolation
signale les problèmes à un point de terminaison de création de rapports (facultatif) qui peut être configuré dans l'en-tête HTTP du CSP. La plupart des informations que nous voulions signaler étaient déjà disponibles. Par conséquent, aucun changement majeur en arrière-plan n'a été nécessaire pour que notre instrumentation fonctionne.
Étape 4: Enregistrez et affichez les problèmes
Petit problème : nous voulions également signaler les problèmes qui se sont produits avant l'ouverture des outils de développement, de la même manière que les messages de la console. Cela signifie que nous ne signalons pas immédiatement les problèmes au niveau du front-end, mais que nous utilisons un espace de stockage qui est renseigné par les problèmes, que les outils de développement soient ouverts ou non. Une fois DevTools ouvert (ou tout autre client CDP associé), tous les problèmes précédemment enregistrés peuvent être rejoués à partir du stockage.
Le travail côté backend est terminé. Nous devons maintenant nous concentrer sur la façon de signaler le problème côté frontend.
Étape 5: Concevoir le texte des problèmes
La conception du texte des problèmes est un processus qui implique plusieurs équipes en plus de la nôtre. Par exemple, nous nous appuyons souvent sur les insights de l'équipe qui implémente une fonctionnalité (dans ce cas, l'équipe CSP) et bien sûr sur l'équipe DevRel, qui conçoit la façon dont les développeurs Web sont censés gérer un certain type de problème. Le texte du problème est généralement affiné jusqu'à ce qu'il soit finalisé.
Habituellement, l'équipe DevTools commence par une ébauche de ce qu'elle imagine:
## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site
## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.
Usage of content from not included sources is restricted to strengthen the security of your entire site.
## Specific information
### VIOLATED DIRECTIVES
`img-src 'self'`
### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg
## Specific information
https://web.dev/strict-csp/
Après l'itération, nous sommes arrivés à:
Comme vous pouvez le constater, l'implication de l'équipe chargée des fonctionnalités et de l'équipe DevRel rend la description beaucoup plus claire et précise.
Les problèmes liés à CSP sur votre page sont également disponibles dans l'onglet dédié aux violations CSP.
Déboguer les problèmes liés à Trusted Types
Sans les bons outils pour les développeurs, il peut être difficile de travailler à grande échelle avec un testeur de confiance.
Amélioration de l'impression dans la console
Lorsque nous utilisons des objets approuvés, nous souhaitons afficher au moins la même quantité d'informations que pour leur équivalent non approuvé. Malheureusement, aucune information sur l'objet encapsulé ne s'affiche actuellement lors de l'affichage d'un objet de confiance.
C'est parce que la valeur affichée dans la console provient de l'appel de .valueOf()
sur l'objet par défaut. Toutefois, dans le cas d'un type de confiance, la valeur renvoyée n'est pas très utile. Nous aimerions plutôt obtenir quelque chose de semblable à ce que vous obtenez lorsque vous appelez .toString()
. Pour ce faire, nous devons modifier V8 et Blink afin d'introduire une gestion spéciale pour les objets de type approuvés.
Bien que, pour des raisons historiques, ce traitement personnalisé ait été effectué dans la version 8, une telle approche présente d'importants inconvénients. De nombreux objets nécessitent un affichage personnalisé, mais leur type est le même au niveau JS. Étant donné que V8 est en JavaScript pur, il ne peut pas distinguer les concepts correspondant à une API Web, tels que le type de confiance. C'est pourquoi V8 doit demander à son intégrateur (Blink) de l'aider à les distinguer.
Par conséquent, déplacer cette partie du code vers Blink ou tout autre outil d'intégration semble être un choix logique. Outre le problème exposé, les fonctionnalités suivantes offrent de nombreux autres avantages:
- Chaque intégrateur peut générer sa propre description.
- Il est beaucoup plus facile de générer la description via l'API Blink.
- Blink a accès à la définition d'origine de l'objet. Par conséquent, si nous utilisons
.toString()
pour générer la description, il n'y a aucun risque que.toString()
soit redéfini.
Arrêt en cas de non-respect (en mode "Rapport uniquement")
Actuellement, le seul moyen de déboguer les cas de non-respect des règles de temps de chargement consiste à définir des points d'arrêt sur les exceptions JavaScript. Étant donné que les violations du TT forcés déclenchent une exception, cette fonctionnalité peut s'avérer utile. Toutefois, dans des scénarios réels, vous avez besoin d'un contrôle plus précis des cas de non-respect des règles de TT. Plus précisément, nous souhaitons que la rupture ne se produise que pour les cas de non-respect des règles de temps de chargement (et non pour les autres exceptions), qu'elle se produise également en mode "Rapport uniquement" et qu'elle distingue les différents types de non-respect des règles de temps de chargement.
DevTools est déjà compatible avec un large éventail de points d'arrêt. L'architecture est donc très extensible. Pour ajouter un type de point d'arrêt, vous devez modifier le backend (Blink), la CDP et l'interface.
Nous devrions introduire une nouvelle commande CDP, appelons-la setBreakOnTTViolation
. Cette commande sera utilisée par le frontend pour indiquer au backend le type d'infractions de TT qu'il doit détecter. Le backend, en particulier InspectorDOMDebuggerAgent
, fournit une "sonde", onTTViolation()
, qui sera appelée chaque fois qu'une violation de TT se produit. Ensuite, InspectorDOMDebuggerAgent
vérifie si cette violation doit déclencher un point d'arrêt et, le cas échéant, envoie un message à l'interface pour suspendre l'exécution.
Qu'est-ce qui a été fait et que se passe-t-il ensuite ?
Depuis l'apparition des problèmes décrits ici, l'onglet Problèmes a subi de nombreux changements:
- Son interconnexion avec les autres panneaux de DevTools a été améliorée.
- La signalisation de plusieurs autres problèmes a été déplacée vers l'onglet Problèmes: faible contraste, activité Web fiable, mode quirks, API Attribution Reporting et problèmes liés à CORS, entre autres.
- Vous avez désormais la possibilité de masquer les problèmes.
À l'avenir, nous prévoyons d'utiliser l'onglet Issues (Problèmes) pour identifier davantage de problèmes, ce qui permettra à long terme de décharger la console du flux de messages d'erreur illisibles.
Télécharger les canaux de prévisualisation
Envisagez d'utiliser Chrome Canary, Dev ou Bêta comme navigateur de développement par défaut. Ces versions preview vous permettent d'accéder aux dernières fonctionnalités des outils de développement, de tester des API de plate-forme Web de pointe et de détecter les problèmes sur votre site avant vos utilisateurs.
Contacter l'équipe des outils pour les développeurs Chrome
Utilisez les options suivantes pour discuter des nouvelles fonctionnalités, des mises à jour ou de tout autre élément lié aux outils pour les développeurs.
- Envoyez-nous vos commentaires et vos demandes de fonctionnalités sur crbug.com.
- Signalez un problème dans les outils de développement à l'aide de l'icône Plus d'options > Aide > Signaler un problème dans les outils de développement dans les outils de développement.
- Envoyez un tweet à @ChromeDevTools.
- Laissez des commentaires sur les vidéos YouTube sur les nouveautés dans les outils de développement ou sur les vidéos YouTube de conseils sur les outils de développement.