fix: allow Clerk's frontend API host in CSP script-src

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.
This commit is contained in:
admin committed 2026-09-01 20:23:24 +02:00
1 parent f56d1c7cb1
commit 99d9e5813e
1 file changed
+23 -1
+23 -1
View File
@@ -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()}`,