From 99d9e5813e7a97f95d0cc7fe87561300652ccd9e Mon Sep 17 00:00:00 2001 From: neodk2004 Date: Tue, 1 Sep 2026 20:23:24 +0200 Subject: [PATCH] fix: allow Clerk's frontend API host in CSP script-src MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clerk's clerkMiddleware auto-adds its frontend API host to connect-src but not script-src, so the initial (unversioned) clerk.browser.js/ ui.browser.js load was blocked by strict-dynamic before the 307 redirect to the versioned URL — two CSP violations reported to /api/csp-report on every page that renders Clerk UI, dragging the Best Practices Lighthouse score down. Derives the host from the publishable key (same approach as the existing Supabase/GlitchTip hostname helpers) instead of hardcoding it. --- src/proxy.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/proxy.ts b/src/proxy.ts index c6ed37c..a2811a0 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -53,6 +53,22 @@ function getSupabaseHostname(): string { return "*.supabase.co"; } +function getClerkFrontendApiHostname(): string { + // A Clerk publishable key is base64(`${frontendApiHost}$`) after its + // pk_test_/pk_live_ prefix — this middleware runs on the Edge runtime, so + // atob (not Buffer) for the decode. + const key = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY; + if (key) { + try { + const encoded = key.replace(/^pk_(test|live)_/, ""); + return atob(encoded).replace(/\$$/, ""); + } catch { + /* fall through */ + } + } + return "clerk.pawfeed.org"; +} + function getGlitchtipHostname(): string { const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; if (dsn) { @@ -154,7 +170,13 @@ export default clerkMiddleware( strict: true, reportTo: "/api/csp-report", directives: { - "script-src": ["unsafe-eval", "'report-sample'"], + // Clerk's own middleware adds its frontend API host to connect-src + // automatically, but NOT to script-src — without this, the initial + // (unversioned) clerk.browser.js/ui.browser.js load is blocked by + // 'strict-dynamic' before the 307 redirect to the versioned URL, + // producing two CSP violations (reported to /api/csp-report) on + // every page load that renders Clerk UI. + "script-src": [`https://${getClerkFrontendApiHostname()}`, "unsafe-eval", "'report-sample'"], "img-src": [`https://${getSupabaseHostname()}`, "https://image.mux.com", "blob:"], "connect-src": [ `https://${getSupabaseHostname()}`,