Zusammenfassung

  • Der erste öffentliche W3C-Entwurf zur Content Security Policy vom 29. November 2011 schlug vor, dass Websites zulässige Quellen für Ressourcen erklären und Browser Ladevorgänge daran prüfen.
  • Die Level-2-Empfehlung vom 15. Dezember 2016 beschrieb durchgesetzte Regeln, einen reinen Berichtsmodus sowie Nonces und Hashes für ausgewählte eingebettete Skripte. Die Website schrieb die Liste; der Browser stand an der Tür.

Die Website hatte eine Feier veranstaltet und die Einladungen verlegt. Ein Skript kam vom vertrauten Anbieter, ein zweites von einem Zusatz, an dessen Einbau sich niemand erinnerte. Bilder und Schriften standen an, dahinter warteten Verbindungen zu weiter entfernten Diensten. In der Menge versuchte unerwünschter Code, wie ein alter Bekannter auszusehen. Ein Türsteher ließ sich finden. Schwerer war es, ihm eine brauchbare Gästeliste zu geben.

Der erste öffentliche Arbeitsentwurf des W3C zur Content Security Policy vom 29. November 2011 beschrieb diese Arbeitsteilung. Seine Zusammenfassung stellte eine deklarative Richtlinie vor, mit der Webanwendungen die Herkunft geladener Ressourcen beschränken konnten, um Inhaltsinjektionen einschließlich Cross-Site-Scripting einzudämmen. Die Website benannte akzeptierte Quellen. Der Browser verglich konkrete Ladeanforderungen mit dieser Erklärung.

Die Liste war genauer als ein pauschaler Stempel „vertrauenswürdig“. Der Entwurf unterschied default-src von Regeln für Skripte, Bilder, Stile, Schriften, Frames, Medien und Verbindungen. Fotos konnten aus mehreren Adressen stammen, während ausführbarer Code nur aus einem engeren Kreis kam. Das Bild an der Wand braucht schließlich keinen Schlüssel zum Lichtpult der Bühne. Verschiedene Ressourcen erhielten verschiedene Zugangsbedingungen.

Die neue Ordnung war auch ein Spiegel für den Betreiber. Die Redaktion oder Entwicklung wusste, welche Lieferanten sie einsetzen wollte; der Browser sah, welche Adressen die Seite tatsächlich anfragte. Die Richtlinie verband beide Sichtweisen. script-src war schnell geschrieben. Herauszufinden, ob eine Kampagnenseite von vor Jahren noch an einem vergessenen Baustein hing, war mühsamer. Eine zu kurze Liste konnte einen fremden Code stoppen und zugleich den legitimen Bezahlvorgang beschädigen. Der Fehler lag dann im Gästebuch des Gastgebers.

Die W3C-Empfehlung Content Security Policy Level 2 vom 15. Dezember 2016 bot eine Generalprobe. Mit dem Antwortheader Content-Security-Policy-Report-Only beobachtete der Browser Verstöße gegen einen vorgeschlagenen Plan und ließ die Ressourcen trotzdem laden. Das Dokument führte vor, wie eine Website auf diesem Weg eine Richtlinie entwickeln und anschließend den durchsetzenden Header Content-Security-Policy verwenden konnte. Zuerst führte der Türsteher Strichliste; später spannte er die Kordel.

Die Meldungen konnten vergessene Abhängigkeiten sichtbar machen: eine Schrift von einer überraschenden Adresse, eine Analyseverbindung auf einer alten Seite, einen Dienst, für den niemand mehr zuständig war. Der Browser meldete die beobachtete Anfrage. Das Team musste entscheiden, ob sie zum Produkt gehörte, ob die Seite geändert werden sollte oder ob die Regel zu eng war. Der Berichtsmodus zeigte die Differenz zwischen der sauberen Skizze im Besprechungsraum und der Website, die tatsächlich lief.

Auch der Ort der Richtlinie war wichtig. Die Empfehlung von 2016 bevorzugte den HTTP-Antwortheader, den der Browser zu Beginn der Verarbeitung erhält. Eine Richtlinie in einem früh platzierten HTML-meta-Element war ebenfalls möglich. Sie erfasste jedoch keine Inhalte, die schon davor geladen worden waren, und bot keinen reinen Berichtsmodus. Ein Schild im Foyer, das erst nach dem Einlass der Hälfte des Publikums aufgehängt wird, taugt wenig für die Eingangskontrolle.

Eingebettete Skripte machten den Einlass besonders schwierig. Manche Seiten brauchten sie tatsächlich. Eine allgemeine Erlaubnis für eingebetteten Code hätte aber auch injiziertem Code einen Platz am Tisch angeboten. Level 2 beschrieb Nonces und Hashes, mit denen sich bestimmte Skripte auswählen ließen. Ein frischer Zufallswert konnte in der Antwortregel und in den gewünschten Skriptelementen stehen; ein Hash passte zu genauem Skriptinhalt. So gab die Website einzelnen Gästen eine Einladung, statt jeden Zettel mit der Aufschrift JavaScript durchzuwinken.

Weitere Türen kamen hinzu. img-src regelte Bilder, connect-src bestimmte Verbindungen, base-uri die Basis relativer Adressen, form-action die Ziele von Formularen und frame-ancestors die Seiten, die die Website in einem Frame zeigen durften. Jede Direktive betraf eine andere Handlung. Der Betreiber entschied, was er zulassen wollte, und der Browser prüfte die Handlung beim tatsächlichen Laden.

Die W3C-Veröffentlichungsgeschichte von CSP Level 2 zeichnet den Weg der Entwürfe bis zur Empfehlung vom Dezember 2016 nach. Das sind Daten der Spezifikation. Die bleibende Änderung steckt in der Arbeitsroutine: Eine Website beschreibt ihre beabsichtigten Quellen, der Browser prüft Ressourcen, und Berichte zeigen, wo die Seite anders handelt als geplant. Der Türsteher bekam bessere Anweisungen. Der Gastgeber musste seine eigene Feier kennenlernen.

Leser prüfen keinen script-src-Header, bevor sie eine Meldung lesen oder eine Rechnung bezahlen. Sie erleben eine funktionierende Seite oder eine kaputte Funktion, weil ein legitimer Name im Buch fehlte. Die Gästeliste arbeitet hinter der Bühne. Der Browser kann Code ohne Einladung abweisen. Die Website muss allerdings endlich sagen können, wen sie eingeladen hat. Manchmal beginnt technischer Fortschritt mit einer ziemlich unangenehmen Anwesenheitskontrolle.