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 d9eeef4..0000000 --- a/src/lib/server/csrf.ts +++ /dev/null @@ -1,64 +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'; - -import Logs from "$lib/server/log" - -/** - * 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) { - 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 }); - } - 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 add663a..3931d77 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -25,12 +25,11 @@ const config = { 'script-src': ['self'], 'report-uri': ['/'] } - }, - csrf: { - checkOrigin: false, } }, + checkOrigin: true, + //warningFilter: (warning) => !warning.code.startsWith('a11y') };