From f56b707cb748ed2281ff4ebed747e28b47831aef Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 2 Aug 2025 16:12:33 +0200 Subject: [PATCH 1/3] revert 25ece0e1f9d4dd710995aab21a5f8ac633e44702 revert fixed broken checkOrigin rule in svelte.config --- svelte.config.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/svelte.config.js b/svelte.config.js index add663a..a4a5a9d 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -25,12 +25,11 @@ const config = { 'script-src': ['self'], 'report-uri': ['/'] } - }, - csrf: { - checkOrigin: false, } }, + checkOrigin: false, + //warningFilter: (warning) => !warning.code.startsWith('a11y') }; -- 2.40.1 From 7d1e6b9451185bc2d71d4dbe119b562966500fd0 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 2 Aug 2025 16:12:53 +0200 Subject: [PATCH 2/3] revert 2fb4f8ac98cb30eadcadb11e50dc4468fe0ee5c5 revert added log statement to csrf validation --- src/lib/server/csrf.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/server/csrf.ts b/src/lib/server/csrf.ts index d9eeef4..b52f21e 100644 --- a/src/lib/server/csrf.ts +++ b/src/lib/server/csrf.ts @@ -5,8 +5,6 @@ import type { Handle } from '@sveltejs/kit'; import { json, text } from '@sveltejs/kit'; -import Logs from "$lib/server/log" - /** * CSRF protection middleware for SvelteKit. * @@ -30,8 +28,6 @@ export function csrf(allowedPaths: string[], allowedOrigins: string[] = []): Han !allowedPaths.includes(url.pathname); // Path is not explicitly allowed if (forbidden) { - Logs.route.warn("Blocked request due to csrf violation") - const message = `Cross-site ${request.method} form submissions are forbidden`; if (request.headers.get('accept') === 'application/json') { return json({ message }, { status: 403 }); -- 2.40.1 From 377f9ecfd5cd0d907041927d0661f4d0d8d9ac25 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 2 Aug 2025 16:13:19 +0200 Subject: [PATCH 3/3] revert 098317cbcb11ae850f10c07a39c71ae0bf1e3368 revert implemented custom csrf --- src/hooks.server.ts | 7 ++--- src/lib/server/csrf.ts | 60 ------------------------------------------ svelte.config.js | 2 +- 3 files changed, 3 insertions(+), 66 deletions(-) delete mode 100644 src/lib/server/csrf.ts diff --git a/src/hooks.server.ts b/src/hooks.server.ts index e24cfbd..4b380a6 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,11 +1,8 @@ import type { Handle } from "@sveltejs/kit"; import { error, redirect } from "@sveltejs/kit"; -import { sequence } from "@sveltejs/kit/hooks"; import { env } from "$env/dynamic/private" -import { csrf } from "$lib/server/csrf" - import SessionStore from "$lib/server/session_store" import { init_db, close_db, create_user, do_users_exist } from "$lib/server/database"; @@ -66,7 +63,7 @@ process.on("uncaughtExceptionMonitor", (error, origin) => { await init(); -export let handle: Handle = sequence(csrf([], []), async function ({ event, resolve }) { +export let handle: Handle = async function ({ event, resolve }) { event.locals.setup = local_setup Logs.route.debug(`incoming ${event.request.method} request to: ${event.url.href} (route id: ${event.route.id})`); @@ -109,4 +106,4 @@ export let handle: Handle = sequence(csrf([], []), async function ({ event, reso event.locals.user = user; return await resolve(event); -}) +} diff --git a/src/lib/server/csrf.ts b/src/lib/server/csrf.ts deleted file mode 100644 index b52f21e..0000000 --- a/src/lib/server/csrf.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Imported and adapted from https://gist.github.com/Maxiviper117/95a31750b74510bbb413d2e4ae20b4e8 on 27.07.2025 - * */ - -import type { Handle } from '@sveltejs/kit'; -import { json, text } from '@sveltejs/kit'; - -/** - * CSRF protection middleware for SvelteKit. - * - * @param allowedPaths - Paths that bypass CSRF protection. - * @param allowedOrigins - Trusted origins that can submit cross-origin forms. - * @returns SvelteKit handle function. - */ -export function csrf(allowedPaths: string[], allowedOrigins: string[] = []): Handle { - return async ({ event, resolve }) => { - const { request, url } = event; - const requestOrigin = request.headers.get('origin'); - const isSameOrigin = requestOrigin === url.origin; - const isAllowedOrigin = allowedOrigins.includes(requestOrigin ?? ''); - - // Block form submissions that don't match CSRF rules - const forbidden = - isFormContentType(request) && - ['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method) && - !isSameOrigin && // Not from same origin - !isAllowedOrigin && // Not in allowed origins - !allowedPaths.includes(url.pathname); // Path is not explicitly allowed - - if (forbidden) { - const message = `Cross-site ${request.method} form submissions are forbidden`; - if (request.headers.get('accept') === 'application/json') { - return json({ message }, { status: 403 }); - } - return text(message, { status: 403 }); - } - - return resolve(event); - }; -} - -/** - * Check if request content type matches given types. - */ -function isContentType(request: Request, ...types: string[]) { - const type = request.headers.get('content-type')?.split(';', 1)[0].trim() ?? ''; - return types.includes(type.toLowerCase()); -} - -/** - * Determines if a request is a form submission. - */ -function isFormContentType(request: Request) { - return isContentType( - request, - 'application/x-www-form-urlencoded', - 'multipart/form-data', - 'text/plain' - ); -} diff --git a/svelte.config.js b/svelte.config.js index a4a5a9d..3931d77 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -28,7 +28,7 @@ const config = { } }, - checkOrigin: false, + checkOrigin: true, //warningFilter: (warning) => !warning.code.startsWith('a11y') }; -- 2.40.1