sveltekit-clerk Svelte Themes

Sveltekit Clerk

SvelteKit + Clerk CSP Nonce Reproduction

Minimal reproduction demonstrating that clerk.browser.js creates inline <script> elements at runtime that don't carry the nonce attribute, breaking nonce-based Content Security Policy.

The problem

When using svelte-clerk with a per-request nonce in the CSP header:

script-src 'nonce-{uuid}' 'strict-dynamic'

The initial clerk.browser.js script loads correctly (the nonce is applied via the nonce prop on <ClerkProvider>). However, after loading, clerk.browser.js creates inline <script> elements at runtime that don't have the nonce attribute. These are blocked by CSP:

Executing inline script violates the following Content Security Policy
directive 'script-src 'nonce-xxx' 'strict-dynamic''.

This prevents Clerk from initializing on the client side.

Expected behavior

clerk.browser.js should read the nonce from its own <script> element (set by @clerk/shared's loadClerkJSScript) and apply it to any inline <script> elements it creates at runtime.

Setup

cp .env.example .env
# Add your Clerk keys to .env
npm install
npm run dev

Visit http://localhost:5173. You'll be redirected to /sign-in. After signing in, the home page will show a skeleton/blank because Clerk's client-side scripts are blocked by CSP.

Open the browser console to see the CSP violation errors.

Key files

  • src/hooks.server.ts — Generates per-request nonce, sets enforcing CSP header, adds nonce to script tags via transformPageChunk
  • src/routes/+layout.svelte — Passes nonce to <ClerkProvider nonce={data.cspNonce}>

Workaround

Replace the nonce-based script-src with 'self' 'unsafe-inline' + domain allowlist. This works but is flagged in enterprise security audits.

Top categories

Loading Svelte Themes