Full-stack framework
SvelteKit security checklist
The SvelteKit-specific mistakes AI tools ship: PUBLIC_ env leaks, unguarded form actions and +server.ts endpoints, and load data that leaks to the client. Free scan.
SvelteKit is a full-stack Svelte framework where a single route folder mixes server code (+page.server.ts, +server.ts, hooks.server.ts) with universal code (+page.ts) and client components. That blur is exactly where things leak: it is easy to write code that looks server-side but actually runs — and ships — in the browser.
Why SvelteKit apps get shipped insecure
When you ship fast with an AI tool, the model happily wires up form actions, +server.ts endpoints, and load functions without ever asking ‘who is allowed to call this?’ SvelteKit does not add auth for you — every endpoint and action is public until you guard it in hooks.server.ts — and its env-module split (PUBLIC_ vs private) is only as safe as the file you import it into.
The SvelteKit-specific footguns
- Secrets behind the PUBLIC_ prefix: anything read from $env/static/public or $env/dynamic/public is bundled into the client and readable in the browser. Putting an API key in a PUBLIC_ var (or importing $env/static/private into a universal +page.ts) exposes it — SvelteKit only blocks the private modules from client-side files, not a genuinely public-prefixed secret you set yourself.
- Data leaking from universal load: a load function in +page.ts runs on the server on first hit and then again in the browser, so whatever it fetches (full user records, tokens, internal fields) is serialized into the page and reachable client-side. Sensitive fetches belong in +page.server.ts, which never runs in the browser.
- Unauthenticated +server.ts endpoints: each GET/POST handler in a +server.ts file is a public API route. AI-generated CRUD endpoints routinely skip the ‘is this user logged in / allowed?’ check, so anyone can call them directly with curl — a classic IDOR when the handler trusts an id from the request.
- Form actions with no auth or ownership check: named actions in +page.server.ts are hit directly by POST. It is common to validate the input but never verify the session or that the row belongs to the caller, so one user can mutate another user’s data.
- Auth logic that lives in the wrong place: SvelteKit expects the session/auth gate in hooks.server.ts (the handle hook) so it covers every request. Apps that only check auth inside one +page.server.ts leave sibling endpoints and actions wide open, and child routes can load without the parent’s guard.
Scan your SvelteKit app — live routes + repo, free
Trust's framework-aware scan reaches your real routes and endpoints, then checks your code for leaked secrets and vulnerable deps. No signup, about a minute.
Run a free scan →SvelteKit security checklist
- Audit every PUBLIC_ variable and every $env/static/public / $env/dynamic/public import — confirm none of them are actually secrets. Keys, tokens, and connection strings must come from the private env modules and only be imported into .server files.
- Put your auth gate in hooks.server.ts (handle) so it runs on every request, populate event.locals.user there, and treat that as the single source of truth for who is logged in.
- Guard every +server.ts handler and every form action individually: check the session and check ownership/authorization (not just ‘logged in’) before reading or mutating anything — assume each one is directly callable.
- Move any sensitive data fetching out of universal +page.ts and into +page.server.ts, and return only the fields the UI actually renders — never spread a whole DB row into the client.
- Keep SvelteKit’s built-in origin-based CSRF check enabled (csrf.checkOrigin) and do not blanket-disable it; only relax it for specific machine-to-machine routes that truly need it.
- Scan the live URL and the repo before you launch: confirm no PUBLIC_ secret shipped, and probe your form actions and +server.ts routes unauthenticated to prove they reject anonymous callers.
Bottom line
SvelteKit’s server/universal split is powerful but unforgiving: a mislabeled env var or a universal load leaks data straight to the browser, and every form action and +server.ts endpoint is public until you guard it in hooks.server.ts. Trust’s SvelteKit route-extractor reads your real routes and endpoints, hits them like an attacker would, and scans your repo for PUBLIC_ secrets and missing auth — free URL scan, no signup.
Scan another framework
- Next.js securityReact framework
- Astro securityContent-first web framework
- Remix securityFull-stack framework