fix(security): enforce Content-Security-Policy instead of report-only

Mozilla Observatory docked 25 points for CSP being report-only. The
report-only period since 2026-08-12 came back clean in GlitchTip except
6 isolated script-src eval hits on 2026-08-15 (likely react-easy-crop
on the avatar-crop flow) that never recurred. Keep 'unsafe-eval' in
script-src defensively so an enforced policy can't repeat the earlier
incident where a blocked required resource crashed ClerkProvider
app-wide.
This commit is contained in:
2026-08-22 13:51:55 +02:00
parent e89ddc4d32
commit ddbeee759b
+18 -8
View File
@@ -119,17 +119,27 @@ export default clerkMiddleware(
}
},
{
// Report-Only for now — an earlier enforced attempt blanked the whole
// app because ClerkProvider crashes uncaught when a required resource
// gets blocked mid-init. Clerk's own contentSecurityPolicy option (not
// the hand-rolled next.config.ts draft this replaces) already ships the
// 'unsafe-inline'/https: script-src Next.js needs to hydrate, which is
// what the hand-rolled version was missing. Move to enforced only after
// a clean report-only period — see /api/csp-report for the violations.
// Enforced as of 2026-08-22 (Mozilla Observatory docked 25 points for
// Report-Only-only). The report-only period (since 2026-08-12/13) came
// back clean: GlitchTip shows zero CSP violations since 2026-08-16
// (verified via issue_events_issueaggregate on the self-hosted instance)
// except 6 script-src "eval" hits on 2026-08-15 from /pets/[petId] and
// /onboarding/pet — both routes use react-easy-crop for avatar cropping,
// the likely source, and it hasn't recurred since. Clerk's production
// script-src default omits 'unsafe-eval' (see
// node_modules/@clerk/nextjs/.../content-security-policy.js), so an
// enforced policy would hard-block that call if it ever recurs. Adding
// 'unsafe-eval' back here defensively avoids repeating the earlier
// incident where an enforced CSP blanked the whole app (ClerkProvider
// crashed uncaught on a blocked required resource) — it costs nothing
// extra in Mozilla's scoring since 'unsafe-inline'/https:/http: are
// already unconditionally in Clerk's default script-src. Revisit once
// the eval source is confirmed fixed and remove this line.
contentSecurityPolicy: {
reportOnly: true,
reportOnly: false,
reportTo: "/api/csp-report",
directives: {
"script-src": ["unsafe-eval"],
"img-src": [`https://${getSupabaseHostname()}`, "https://image.mux.com", "blob:"],
"connect-src": [
`https://${getSupabaseHostname()}`,