From 5d8d85057d06f07589ce1436d10753b72c62b2a9 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 30 May 2026 11:37:53 +0200 Subject: [PATCH] fix(security): make csrfFetch a function to respect vi.stubGlobal mocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous `export const csrfFetch = makeCsrfFetch(fetch)` captured the global fetch at module evaluation time. Tests that mock fetch via `vi.stubGlobal('fetch', mockFetch)` set up their stub *after* module import, so all calls through csrfFetch bypassed the mock — 21 browser tests saw 0 fetch calls. Changing csrfFetch to a plain function means `fetch` is resolved from the global scope at each call site, picking up whatever stub is in place at call time. Production behaviour is identical; test isolation is restored. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/lib/shared/cookies.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/lib/shared/cookies.ts b/frontend/src/lib/shared/cookies.ts index e507ea81..4b029dbf 100644 --- a/frontend/src/lib/shared/cookies.ts +++ b/frontend/src/lib/shared/cookies.ts @@ -45,8 +45,18 @@ export function makeCsrfFetch(inner: typeof fetch): typeof fetch { * Drop-in replacement for fetch that automatically injects X-XSRF-TOKEN on * all mutating requests (POST, PUT, PATCH, DELETE). Use this everywhere in * client-side code instead of bare fetch + withCsrf(). + * + * Implemented as a function (not a module-level const) so that test stubs + * applied via vi.stubGlobal('fetch', mock) are picked up at call time rather + * than being silently bypassed by a pre-captured reference. */ -export const csrfFetch = makeCsrfFetch(fetch); +export function csrfFetch(input: RequestInfo | URL, init?: RequestInit): Promise { + const method = (init?.method ?? 'GET').toUpperCase(); + if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) { + return fetch(input, withCsrf(init)); + } + return fetch(input, init); +} /** * Extracts the fa_session cookie value from a list of Set-Cookie response headers.