From dd64dffa4d2efc21d24ff70c030234846fd9e057 Mon Sep 17 00:00:00 2001 From: Jay Malhotra <5047192+SapiensAnatis@users.noreply.github.com> Date: Sat, 18 Jan 2025 13:28:32 +0000 Subject: [PATCH] Add Content-Security-Policy (#1229) The mode-watcher bug causing a flash of light mode has been fixed so we can now add a CSP. Still need to add an additional directive due to a Svelte bug --- Website/playwright.config.ts | 3 ++- Website/src/app.html | 3 +++ Website/src/hooks.server.ts | 18 +++++++++++++++++- Website/src/routes/(main)/+layout.svelte | 2 +- Website/src/routes/csp/+server.ts | 9 +++++++++ Website/svelte.config.js | 22 ++++++++++++++++------ 6 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 Website/src/routes/csp/+server.ts diff --git a/Website/playwright.config.ts b/Website/playwright.config.ts index b0061f824..9d053cfa1 100644 --- a/Website/playwright.config.ts +++ b/Website/playwright.config.ts @@ -9,7 +9,8 @@ const config: PlaywrightTestConfig = { timeout: 120000 }, use: { - baseURL: 'http://localhost:3001' + baseURL: 'http://localhost:3001', + bypassCSP: true }, updateSnapshots: process.env.UPDATE_SNAPSHOTS ? 'all' : 'missing', ignoreSnapshots: !process.env.CI, diff --git a/Website/src/app.html b/Website/src/app.html index 4133ffafd..dd4f33e3a 100644 --- a/Website/src/app.html +++ b/Website/src/app.html @@ -11,6 +11,9 @@ Dawnshard %sveltekit.head% +
%sveltekit.body%
diff --git a/Website/src/hooks.server.ts b/Website/src/hooks.server.ts index 9d8e4e27f..1156ea760 100644 --- a/Website/src/hooks.server.ts +++ b/Website/src/hooks.server.ts @@ -1,6 +1,8 @@ import { randomUUID } from 'node:crypto'; import type { Handle, HandleFetch, HandleServerError } from '@sveltejs/kit'; +import { sequence } from '@sveltejs/kit/hooks'; +import { generateSetInitialModeExpression } from 'mode-watcher'; import { env } from '$env/dynamic/private'; import { PUBLIC_ENABLE_MSW } from '$env/static/public'; @@ -50,12 +52,24 @@ export const handleFetch: HandleFetch = ({ request, event, fetch }) => { return fetch(request); }; -export const handle: Handle = ({ event, resolve }) => { +const handleHeadScript: Handle = ({ event, resolve }) => { + return resolve(event, { + transformPageChunk: ({ html }) => { + return html.replace('%modewatcher.snippet%', generateSetInitialModeExpression({})); + } + }); +}; + +const handleLogger: Handle = ({ event, resolve }) => { event.locals.logger = createLogger({ requestPath: new URL(event.request.url).pathname, requestId: randomUUID() }); + return resolve(event); +}; + +const handleAuth: Handle = ({ event, resolve }) => { const idToken = event.cookies.get(Cookies.IdToken); if (!idToken) { @@ -77,6 +91,8 @@ export const handle: Handle = ({ event, resolve }) => { return resolve(event); }; +export const handle = sequence(handleHeadScript, handleLogger, handleAuth); + export const handleError: HandleServerError = ({ error, event, status, message }) => { event.locals.logger.error({ error, status, message }, 'Unhandled error occurred: {message}'); }; diff --git a/Website/src/routes/(main)/+layout.svelte b/Website/src/routes/(main)/+layout.svelte index c281de385..9501c6ed8 100644 --- a/Website/src/routes/(main)/+layout.svelte +++ b/Website/src/routes/(main)/+layout.svelte @@ -14,7 +14,7 @@ - +
diff --git a/Website/src/routes/csp/+server.ts b/Website/src/routes/csp/+server.ts new file mode 100644 index 000000000..759be0504 --- /dev/null +++ b/Website/src/routes/csp/+server.ts @@ -0,0 +1,9 @@ +import type { RequestHandler } from './$types'; + +export const POST: RequestHandler = async ({ locals, request }) => { + const violation = await request.json(); + + locals.logger.error({ violation }, 'CSP violation reported: {violation}'); + + return new Response(null, { status: 200 }); +}; diff --git a/Website/svelte.config.js b/Website/svelte.config.js index 0f8797ad7..a440cd302 100644 --- a/Website/svelte.config.js +++ b/Website/svelte.config.js @@ -1,6 +1,13 @@ import adapter from '@sveltejs/adapter-node'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +const scriptCsp = [ + 'self', + // https://github.com/sveltejs/svelte/issues/14014 + 'unsafe-hashes', + 'sha256-7dQwUgLau1NFCCGjfn9FsYptB6ZtWxJin6VohGIu20I=' +]; + /** @type {import('@sveltejs/kit').Config} */ const config = { // Consult https://kit.svelte.dev/docs/integrations#preprocessors @@ -13,13 +20,16 @@ const config = { $shadcn: './src/lib/shadcn', $static: './static', $main: './src/routes/(main)' + }, + csp: { + directives: { + 'script-src': scriptCsp + }, + reportOnly: { + 'script-src': scriptCsp, + 'report-uri': ['/csp'] + } } - // Blocked by https://github.com/svecosystem/mode-watcher/issues/92 - // csp: { - // directives: { - // 'script-src': ['self'] - // } - // } } };