Fix Shadow API Exposure in SvelteKit
Shadow APIs in SvelteKit represent a critical attack surface where developers inadvertently expose backend logic through server-only routes without proper gatekeeping. Because SvelteKit abstracts the RPC layer, it's easy to forget that every `+server.js` and `+page.server.js` is a public-facing endpoint. If you aren't enforcing strict session validation and attribute-level filtering at the boundary, you're essentially providing an unauthenticated GraphQL playground for attackers to scrape your DB.
The Vulnerable Pattern
// src/routes/api/user/[id]/+server.js import { json } from '@sveltejs/kit'; import { db } from '$lib/db';
export async function GET({ params }) { // ATTACK VECTOR: No session validation or IDOR check. // An attacker can iterate ‘id’ to dump the entire user table. // Also leaks sensitive fields like ‘password_hash’ and ‘internal_notes’. const user = await db.user.findUnique({ where: { id: params.id } }); return json(user); }
The Secure Implementation
To remediate Shadow API exposure, you must adopt a Zero Trust posture for all server-side files. First, use SvelteKit Hooks to verify JWTs or sessions and inject them into `event.locals`. Second, implement strict Authorization checks inside the handler to ensure the requester owns the resource (fixing IDOR). Third, never return raw ORM objects; use projection (select) to ensure that sensitive metadata like password hashes, reset tokens, or roles never leave the server boundary. If it's not explicitly needed by the UI, it shouldn't be in the JSON response.
// src/routes/api/user/[id]/+server.js import { error, json } from '@sveltejs/kit'; import { db } from '$lib/db';export async function GET({ params, locals }) { // 1. Authenticate via locals (populated in hooks.server.js) if (!locals.session) { throw error(401, ‘Unauthorized’); }
// 2. Authorization: Prevent IDOR (Insecure Direct Object Reference) if (locals.user.id !== params.id && !locals.user.isAdmin) { throw error(403, 'Forbidden'); } const user = await db.user.findUnique({ where: { id: params.id }, // 3. Explicit Projection: Never leak internal state select: { id: true, email: true, profile_pic: true } }); if (!user) throw error(404, 'User not found'); return json(user);
}
Your SvelteKit API
might be exposed to Shadow API Exposure
74% of SvelteKit apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.