From 43aacd9f60d7cdca937426fdbb2ac1914af12b38 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 29 Apr 2026 01:09:52 +0200 Subject: [PATCH] fix(transcription): UUID-guard saveBlock path interpolation Sina #5505 concern 1: doc.id and blockId are server-trusted today, but the path-interpolation pattern is repeated three times across the route and the autosave hook. Validate both ids against the standard UUID regex before any fetch fires so a future feature taking user-supplied ids cannot silently introduce a path-injection vector. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/routes/documents/[id]/+page.svelte | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/routes/documents/[id]/+page.svelte b/frontend/src/routes/documents/[id]/+page.svelte index 88540618..0baa8985 100644 --- a/frontend/src/routes/documents/[id]/+page.svelte +++ b/frontend/src/routes/documents/[id]/+page.svelte @@ -88,11 +88,20 @@ async function loadTranscriptionBlocks() { } } +const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + async function saveBlock( blockId: string, text: string, mentionedPersons: import('$lib/types').PersonMention[] ) { + // Path-injection defence in depth (Sina #5505): both ids are server-controlled + // today, but reject anything that isn't a UUID before interpolating it into + // the URL — a future feature accepting user-supplied ids must not silently + // bypass this check. + if (!UUID_RE.test(doc.id) || !UUID_RE.test(blockId)) { + throw new Error(`Invalid id for save: doc=${doc.id} block=${blockId}`); + } const res = await fetch(`/api/documents/${doc.id}/transcription-blocks/${blockId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' },