In diesem Blogpost geht es um die Implementierung von DevTools-Unterstützung für die Fehlerbehebung bei Problemen mit der Content Security Policy (CSP) mithilfe des vor Kurzem eingeführten Tabs Probleme.
Die Implementierungsarbeit wurde im Rahmen von zwei Praktika durchgeführt: Während der ersten Phase haben wir das allgemeine Meldesystem entwickelt und die Problemmeldungen für drei CSP-Verstöße entworfen. 2. Im Rahmen der zweiten Version haben wir Probleme mit vertrauenswürdigen Typen sowie einige spezielle DevTools-Funktionen für das Debuggen von vertrauenswürdigen Typen hinzugefügt.
Was ist eine Content Security Policy?
Mit einer Content Security Policy (CSP) können Sie bestimmte Verhaltensweisen auf einer Website einschränken, um die Sicherheit zu erhöhen. Mit CSP können Sie beispielsweise Inline-Scripts oder eval
deaktivieren, wodurch die Angriffsfläche für Cross-Site-Scripting-Angriffe (XSS) verringert wird. Eine ausführliche Einführung in CSP finden Sie hier.
Eine besonders neue CSP ist die Richtlinie für vertrauenswürdige Typen(Trusted Types, TT). Sie ermöglicht eine dynamische Analyse, mit der eine große Gruppe von Injection-Angriffen auf Websites systematisch verhindert werden kann. Dazu unterstützt TT eine Website dabei, ihren JavaScript-Code so zu überwachen, dass DOM-Sinks wie innerHTML nur bestimmte Arten von Elementen zugewiesen werden dürfen.
Eine Website kann eine Content Security Policy aktivieren, indem ein bestimmter HTTP-Header eingefügt wird. Mit dem Header content-security-policy: require-trusted-types-for 'script'; trusted-types default
wird beispielsweise die TT-Richtlinie für eine Seite aktiviert.
Jede Richtlinie kann in einem der folgenden Modi ausgeführt werden:
- Erzwingungsmodus: Jeder Richtlinienverstoß ist ein Fehler.
- Nur-Meldungsmodus: Die Fehlermeldung wird als Warnung gemeldet, führt aber nicht zu einem Fehler auf der Webseite.
Probleme mit der Content Security Policy auf dem Tab Probleme implementieren
Ziel dieser Arbeit war es, die Fehlerbehebung bei CSP-Problemen zu verbessern. Bei der Prüfung neuer Probleme folgt das DevTools-Team ungefähr diesem Prozess:
- User Storys definieren Ermitteln Sie im DevTools-Frontend eine Reihe von User Storys, die beschreiben, wie ein Webentwickler das Problem untersuchen müsste.
- Frontend-Implementierung Ermitteln Sie anhand der User Storys, welche Informationen für die Untersuchung des Problems im Front-End erforderlich sind (z. B. eine zugehörige Anfrage, der Name eines Cookies, eine Zeile in einem Script oder einer HTML-Datei usw.).
- Problemerkennung Ermitteln Sie die Stellen im Browser, an denen das Problem in Chrome erkannt werden kann, und instrumentieren Sie die Stelle, um ein Problem zu melden, einschließlich der relevanten Informationen aus Schritt 2.
- Probleme speichern und anzeigen Speichern Sie die Probleme an einem geeigneten Ort und stellen Sie sie den DevTools zur Verfügung, sobald sie geöffnet sind.
- Text für Probleme entwerfen Erstellen Sie einen Erläuterungstext, der dem Webentwickler hilft, das Problem zu verstehen und vor allem zu beheben.
Schritt 1: User Storys für CSP-Probleme definieren
Bevor wir mit der Implementierung begannen, haben wir ein Designdokument mit User Storys erstellt, um besser zu verstehen, was wir tun mussten. Beispielsweise haben wir die folgende User Story aufgeschrieben:
Als Entwickler, der gerade festgestellt hat, dass ein Teil meiner Website blockiert ist, möchte ich Folgendes herausfinden: ...ob CSP ein Grund für blockierte Iframes / Bilder auf meiner Website ist ...welche CSP-Richtlinie die Blockierung einer bestimmten Ressource verursacht ...wie ich die CSP meiner Website ändern kann, um die Anzeige derzeit blockierter Ressourcen / die Ausführung derzeit blockierter JS-Scripts zuzulassen.
Um diese User Story zu untersuchen, haben wir einige einfache Beispiel-Webseiten mit den für uns interessanten CSP-Verstößen erstellt und uns mit den Beispielseiten vertraut gemacht, um uns mit dem Prozess vertraut zu machen. Hier sind einige Beispiel-Webseiten. Öffnen Sie die Demo mit geöffnetem Tab Probleme:
- CSP-Probleme
- Verstöße gegen vertrauenswürdige Typen
- Verstöße gegen vertrauenswürdige Typen – Modus „Nur melden“
Dabei haben wir festgestellt, dass der Speicherort der Quelle die wichtigste Information für die Fehlerbehebung bei CSP-Problemen ist. Außerdem fanden wir es nützlich, den zugehörigen Iframe und die Anfrage schnell zu finden, falls eine Ressource blockiert wurde. Ein direkter Link zum HTML-Element im Bereich Elemente in den DevTools wäre ebenfalls hilfreich.
Schritt 2: Front-End-Implementierung
Auf dieser Grundlage haben wir den ersten Entwurf der Informationen erstellt, die wir über das Chrome DevTools Protocol (CDP) in den DevTools verfügbar machen wollten:
Unten finden Sie einen Auszug aus 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
Die obige Definition codiert im Wesentlichen eine JSON-Datenstruktur. Sie ist in einer einfachen Sprache namens PDL (Protocol Data Language) geschrieben. PDL wird für zwei Zwecke verwendet. Zuerst generieren wir mit PDL die TypeScript-Definitionen, auf die das DevTools-Frontend angewiesen ist. Aus der obigen PDL-Definition wird beispielsweise die folgende TypeScript-Schnittstelle generiert:
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;
}
Zweitens, und wahrscheinlich wichtiger, generieren wir aus der Definition eine C++-Bibliothek, die das Generieren und Senden dieser Datenstrukturen vom C++-Chromium-Back-End an das DevTools-Front-End übernimmt. Mit dieser Bibliothek kann ein ContentSecurityPolicyIssueDetails
-Objekt mit dem folgenden C++-Code erstellt werden:
protocol::Audits::ContentSecurityPolicyIssueDetails::create()
.setViolatedDirective(d->violated_directive)
.setIsReportOnly(d->is_report_only)
.setContentSecurityPolicyViolationType(BuildViolationType(
d->content_security_policy_violation_type)))
.build();
Nachdem wir uns entschieden hatten, welche Informationen wir zur Verfügung stellen wollten, mussten wir herausfinden, wo wir diese Informationen in Chromium finden.
Schritt 3: Problemerkennung
Damit die Informationen dem Chrome DevTools Protocol (CDP) im im letzten Abschnitt beschriebenen Format zur Verfügung gestellt werden konnten, mussten wir den Ort finden, an dem die Informationen im Backend tatsächlich verfügbar waren. Glücklicherweise gab es im CSP-Code bereits ein Nadelöhr, das für den Modus „Nur melden“ verwendet wurde, an dem wir anknüpfen konnten: ContentSecurityPolicy::ReportViolation
meldet Probleme an einen (optionalen) Meldeendpunkt, der im CSP-HTTP-Header konfiguriert werden kann. Die meisten Informationen, die wir erfassen wollten, waren bereits verfügbar. Daher waren keine großen Änderungen am Back-End erforderlich, damit unsere Instrumentierung funktionierte.
Schritt 4: Probleme speichern und anzeigen
Eine kleine Komplikation besteht darin, dass wir auch Probleme melden wollten, die vor dem Öffnen der DevTools aufgetreten sind, ähnlich wie bei der Verarbeitung von Konsolennachrichten. Das bedeutet, dass Probleme nicht direkt an das Front-End gemeldet werden, sondern in einem Speicher abgelegt werden, der unabhängig davon, ob DevTools geöffnet ist oder nicht, mit Problemen gefüllt wird. Sobald DevTools geöffnet ist (oder ein anderer CDP-Client verbunden ist), können alle zuvor aufgezeichneten Probleme aus dem Speicher wiedergegeben werden.
Damit waren die Back-End-Arbeiten abgeschlossen und wir mussten uns nun darauf konzentrieren, wie wir das Problem im Front-End sichtbar machen.
Schritt 5: Text für Probleme entwerfen
Bei der Formulierung des Problemtexts sind neben unserem Team noch mehrere andere beteiligt. So stützen wir uns beispielsweise oft auf die Erkenntnisse des Teams, das eine Funktion implementiert (in diesem Fall das CSP-Team), und natürlich auf das DevRel-Team, das festlegt, wie Webentwickler mit einer bestimmten Art von Problem umgehen sollen. Der Problemtext wird in der Regel noch etwas überarbeitet, bis er fertig ist.
Normalerweise beginnt das DevTools-Team mit einem groben Entwurf seiner Vorstellung:
## 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/
Nach der Iteration haben wir Folgendes erreicht:
Wie Sie sehen, wird die Beschreibung durch die Einbeziehung des Feature-Teams und des DevRel-Teams viel klarer und präziser.
CSP-Probleme auf Ihrer Seite können auch auf dem Tab speziell für CSP-Verstöße gefunden werden.
Probleme mit vertrauenswürdigen Typen beheben
Ohne die richtigen Entwicklertools kann die Arbeit mit TT im großen Maßstab eine Herausforderung sein.
Verbessertes Konsolendrucken
Bei der Arbeit mit vertrauenswürdigen Objekten möchten wir mindestens die gleiche Menge an Informationen anzeigen wie bei nicht vertrauenswürdigen Objekten. Leider werden beim Anzeigen eines vertrauenswürdigen Objekts derzeit keine Informationen zum verpackten Objekt angezeigt.
Das liegt daran, dass der in der Konsole angezeigte Wert standardmäßig durch Aufrufen von .valueOf()
auf dem Objekt ermittelt wird. Im Fall von „Trusted Type“ ist der zurückgegebene Wert jedoch nicht sehr nützlich. Stattdessen möchten wir etwas Ähnliches wie bei einem Anruf bei .toString()
. Dazu müssen wir V8 und Blink ändern, um eine spezielle Verarbeitung für Objekte des vertrauenswürdigen Typs einzuführen.
Aus historischen Gründen wurde diese benutzerdefinierte Verarbeitung in V8 durchgeführt. Ein solcher Ansatz hat jedoch wichtige Nachteile. Es gibt viele Objekte, die eine benutzerdefinierte Darstellung erfordern, deren Typ aber auf JS-Ebene identisch ist. Da V8 reines JS ist, kann es keine Konzepte unterscheiden, die einer Web-API entsprechen, z. B. einen vertrauenswürdigen Typ. Aus diesem Grund muss V8 seinen Embedder (Blink) um Hilfe bitten, um sie zu unterscheiden.
Daher ist es sinnvoll, diesen Teil des Codes zu Blink oder einem anderen Embedder zu verschieben. Neben dem beschriebenen Problem gibt es noch viele weitere Vorteile:
- Für jeden Embedder kann eine eigene Beschreibung generiert werden.
- Es ist viel einfacher, die Beschreibung über die Blink API zu generieren.
- Blink hat Zugriff auf die ursprüngliche Definition des Objekts. Wenn wir also
.toString()
zum Generieren der Beschreibung verwenden, besteht kein Risiko, dass.toString()
neu definiert wird.
Unterbrechung bei Verstoß (im Modus „Nur Berichterstellung“)
Derzeit ist das Einzige, was Sie tun können, um TT-Verstöße zu beheben, das Setzen von Haltepunkten bei JS-Ausnahmen. Da erzwungene TT-Verstöße eine Ausnahme auslösen, kann diese Funktion nützlich sein. In der Praxis ist jedoch eine detailliertere Steuerung von TT-Verstößen erforderlich. Insbesondere möchten wir nur bei TT-Verstößen (nicht bei anderen Ausnahmen) Unterbrechungen einlegen, auch im reinen Meldemodus, und zwischen den verschiedenen Arten von TT-Verstößen unterscheiden.
DevTools unterstützt bereits eine Vielzahl von Haltepunkten, sodass die Architektur recht erweiterbar ist. Wenn Sie einen neuen Typ von Unterbrechung hinzufügen möchten, sind Änderungen am Backend (Blink), an der CDP und am Frontend erforderlich.
Wir sollten einen neuen CDP-Befehl einführen, nennen wir ihn setBreakOnTTViolation
. Mit diesem Befehl teilt das Frontend dem Backend mit, welche Art von TT-Verstößen es brechen soll. Das Backend, insbesondere InspectorDOMDebuggerAgent
, stellt eine „Probe“ (onTTViolation()
) bereit, die jedes Mal aufgerufen wird, wenn ein TT-Verstoß auftritt. Anschließend prüft InspectorDOMDebuggerAgent
, ob dieser Verstoß einen Haltepunkt auslösen soll. Ist das der Fall, wird eine Nachricht an das Frontend gesendet, um die Ausführung zu pausieren.
Was ist bereits erledigt und was kommt als Nächstes?
Seit der Einführung der hier beschriebenen Probleme hat sich der Tab Probleme erheblich verändert:
- Die Vernetzung mit anderen Bereichen in den DevTools wurde verbessert.
- Die Meldung einer Reihe weiterer Probleme wurde auf den Tab Probleme verschoben: niedriger Kontrast, vertrauenswürdige Webaktivitäten, Quirks-Modus, Attribution Reporting API und CORS-bezogene Probleme.
- Es gibt jetzt die Möglichkeit, Probleme auszublenden.
Künftig werden wir auf dem Tab Probleme weitere Probleme anzeigen. So können wir die Konsole langfristig von unleserlichen Fehlermeldungen befreien.
Vorschaukanäle herunterladen
Verwenden Sie als Standard-Entwicklungsbrowser Chrome Canary, Chrome Dev oder Chrome Beta. Diese Vorabversionen bieten Zugriff auf die neuesten DevTools-Funktionen, ermöglichen den Test moderner Webplattform-APIs und helfen Ihnen, Probleme auf Ihrer Website zu finden, bevor Ihre Nutzer sie bemerken.
Chrome-Entwicklertools-Team kontaktieren
Mit den folgenden Optionen können Sie über neue Funktionen, Updates oder andere Themen im Zusammenhang mit den DevTools sprechen.
- Senden Sie uns Feedback und Funktionsanfragen unter crbug.com.
- Melden Sie ein DevTools-Problem über das Dreipunkt-Menü Weitere Optionen > Hilfe > DevTools-Problem melden.
- Tweeten Sie an @ChromeDevTools.
- Hinterlassen Sie Kommentare unter den YouTube-Videos zu den Neuigkeiten in den DevTools oder den YouTube-Videos mit Tipps zu den DevTools.