diff --git a/svelte.config.js b/svelte.config.js index 5ffdc6b8..e658e1ee 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,5 +1,16 @@ import adapter from "@sveltejs/adapter-static" import {vitePreprocess} from "@sveltejs/vite-plugin-svelte" +import {createHash} from "node:crypto" +import {readFileSync} from "node:fs" + +// Sveltekit hashes the scripts it injects itself, but not the ones app.html carries, so those +// have to be named in script-src by hand. Hashing them here rather than pasting a literal is +// what stops an edit to app.html silently violating the policy. +const appHtmlScripts = [ + ...readFileSync(new URL("./src/app.html", import.meta.url), "utf8").matchAll( + /]*\bsrc=)[^>]*>([\s\S]*?)<\/script>/g, + ), +].map(([, script]) => "sha256-" + createHash("sha256").update(script).digest("base64")) /** @type {import('@sveltejs/kit').Config} */ export default { @@ -19,7 +30,7 @@ export default { }, csp: { directives: { - "script-src": ["self", "wasm-unsafe-eval", "https://plausible.coracle.social", "sha256-NpqGpeZTuPniNAucgyfqzWy9iIHwOswFzPzpigwvp/c="], + "script-src": ["self", "wasm-unsafe-eval", "https://plausible.coracle.social", ...appHtmlScripts], "worker-src": ["self", "blob:"], "style-src": ["self", "unsafe-inline"], "frame-src": ["none"],