SEC004 · Server module-scope state
Severity: warning · Category: security
What it checks
Section titled “What it checks”Flags reassignment (=, +=, ??=, ++, …) of a module-scope let/var from inside a function in a SvelteKit route or hooks file (+page(.server).ts, +layout(.server).ts, +server.ts, hooks.server.ts). Reassignment directly from a request handler gets a stronger message than one in a helper function.
Not flagged: top-level initialisation, const bindings, and mutation-style caches (const cache = new Map() + cache.set(…)) — the latter is a deliberate memoisation pattern, though putting request-derived data in one carries the same risk. src/lib/server/** is not scanned (legitimate singletons live there). Assignments inside SvelteKit’s init hook are also not flagged — it runs once at server startup.
Why it matters
Section titled “Why it matters”SvelteKit’s docs: “Avoid shared state on the server.” A module variable on the server is one instance shared by every user — if an action stores Alice’s form data there, Bob’s next request reads it. The value also silently resets whenever the process restarts.
How to fix
Section titled “How to fix”let user; // ❌ one variable for every user of this server
export const actions = { default: async ({ request, cookies, locals }) => { const data = await request.formData(); user = { name: data.get('name') }; // ❌ NEVER DO THIS
await db.saveUser(locals.session, data); // ✅ per-user persistence }};Authenticate with cookies/locals and persist per-user data to a database. For a deliberate process-wide cache, prefer a const container or add // svelte-vitals-disable-next-line SEC004 above the assignment.