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.
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.
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.
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.
src/hooks.server.ts — Generates per-request nonce, sets enforcing CSP header, adds nonce to script tags via transformPageChunksrc/routes/+layout.svelte — Passes nonce to <ClerkProvider nonce={data.cspNonce}>Replace the nonce-based script-src with 'self' 'unsafe-inline' + domain allowlist. This works but is flagged in enterprise security audits.