Prechádzať zdrojové kódy

Enable trusted-types

This commit adds a policy, and make use of it in the Content-Security-Policy.

I've tested it the best I could, both on a modern browser supporting
trusted-types (Chrome) and on one that doesn't (firefox).

Thanks to @lweichselbaum for giving me a hand to wrap this up!
jvoisin 2 rokov pred
rodič
commit
ed20771194

+ 2 - 2
internal/template/templates/common/layout.html

@@ -36,10 +36,10 @@
 
     {{ if and .user .user.Stylesheet }}
     {{ $stylesheetNonce := nonce }}
-    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; style-src 'self' 'nonce-{{ $stylesheetNonce }}'">
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; style-src 'self' 'nonce-{{ $stylesheetNonce }}'; require-trusted-types-for 'script'; trusted-types ttpolicy;">
     <style nonce="{{ $stylesheetNonce }}">{{ .user.Stylesheet | safeCSS }}</style>
     {{ else }}
-    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *">
+    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data:; media-src *; frame-src *; require-trusted-types-for 'script'; trusted-types ttpolicy;">
     {{ end }}
 
     <script src="{{ route "javascript" "name" "app" "checksum" .app_js_checksum }}" defer></script>

+ 1 - 1
internal/ui/static/js/app.js

@@ -352,7 +352,7 @@ function handleFetchOriginalContent() {
 
         response.json().then((data) => {
             if (data.hasOwnProperty("content") && data.hasOwnProperty("reading_time")) {
-                document.querySelector(".entry-content").innerHTML = data.content;
+                document.querySelector(".entry-content").innerHTML = ttpolicy.createHTML(data.content);
                 const entryReadingtimeElement = document.querySelector(".entry-reading-time");
                 if (entryReadingtimeElement) {
                     entryReadingtimeElement.textContent = data.reading_time;

+ 1 - 1
internal/ui/static/js/bootstrap.js

@@ -129,7 +129,7 @@ document.addEventListener("DOMContentLoaded", () => {
     if ("serviceWorker" in navigator) {
         const scriptElement = document.getElementById("service-worker-script");
         if (scriptElement) {
-            navigator.serviceWorker.register(scriptElement.src);
+	    navigator.serviceWorker.register(ttpolicy.createScriptURL(scriptElement.src));
         }
     }
 

+ 15 - 0
internal/ui/static/js/tt.js

@@ -0,0 +1,15 @@
+let ttpolicy;
+if (window.trustedTypes && trustedTypes.createPolicy) {
+    //TODO: use an allow-list for `createScriptURL`
+    if (!ttpolicy) {
+        ttpolicy = trustedTypes.createPolicy('ttpolicy', {
+            createScriptURL: src => src,
+            createHTML: html => html,
+        });
+    }
+} else {
+    ttpolicy = {
+        createScriptURL: src => src,
+        createHTML: html => html,
+    };
+}

+ 1 - 0
internal/ui/static/static.go

@@ -113,6 +113,7 @@ func GenerateStylesheetsBundles() error {
 func GenerateJavascriptBundles() error {
 	var bundles = map[string][]string{
 		"app": {
+			"js/tt.js", // has to be first
 			"js/dom_helper.js",
 			"js/touch_handler.js",
 			"js/keyboard_handler.js",