From fdab40073dca5894d1ce538046150306b97e305c Mon Sep 17 00:00:00 2001 From: Will Manning Date: Mon, 4 May 2026 14:22:02 -0400 Subject: [PATCH 1/2] Tighten CSP (object-src) and Permissions-Policy; allow Vercel Analytics origin Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Will Manning --- next.config.mjs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 8febb5a..c2f65c2 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -14,7 +14,7 @@ if (!process.env.VELITE_STARTED && (isDev || isBuild)) { // the browser never sees the dynamic code and CSP doesn't need 'unsafe-eval'. const csp = [ "default-src 'self'", - "script-src 'self' 'unsafe-inline' plausible.io", + "script-src 'self' 'unsafe-inline' plausible.io va.vercel-scripts.com", "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob:", "font-src 'self' data:", @@ -23,7 +23,8 @@ const csp = [ "child-src 'self' blob:", "frame-ancestors 'none'", "base-uri 'self'", - "form-action 'self'" + "form-action 'self'", + "object-src 'none'" ].join("; "); // next-plausible v4 requires a `src` URL for the v2 Plausible script. When @@ -58,7 +59,8 @@ const nextConfig = wrapWithPlausible({ }, { key: "Permissions-Policy", - value: "camera=(), microphone=(), geolocation=(), payment=()" + value: + "camera=(), microphone=(), geolocation=(), gyroscope=(), payment=(), usb=(), magnetometer=(), accelerometer=()" }, { key: "Content-Security-Policy", value: csp } ] From 64e712927b8237f3e197c1e501b245c5b45db8f6 Mon Sep 17 00:00:00 2001 From: Will Manning Date: Mon, 4 May 2026 14:29:02 -0400 Subject: [PATCH 2/2] Allow Vercel Live origins for preview deploys Co-Authored-By: Claude Opus 4.7 (1M context) Signed-off-by: Will Manning --- next.config.mjs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index c2f65c2..a8a2d1e 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -12,15 +12,22 @@ if (!process.env.VELITE_STARTED && (isDev || isBuild)) { // MDXRenderer compiles velite-emitted JSX via `new Function(code)`, but it's // a server component — the eval happens at build/SSR time on the server, so // the browser never sees the dynamic code and CSP doesn't need 'unsafe-eval'. +// +// vercel.live (+ vercel.com / assets.vercel.com / wss://ws-us3.pusher.com) is +// the Vercel Live feedback toolbar, injected on preview deploys only. It's +// not loaded in production, so widening these directives doesn't broaden the +// prod attack surface — and a single static CSP is simpler than swapping +// headers per environment. const csp = [ "default-src 'self'", - "script-src 'self' 'unsafe-inline' plausible.io va.vercel-scripts.com", - "style-src 'self' 'unsafe-inline'", - "img-src 'self' data: blob:", - "font-src 'self' data:", - "connect-src 'self' plausible.io vitals.vercel-insights.com", + "script-src 'self' 'unsafe-inline' plausible.io va.vercel-scripts.com vercel.live", + "style-src 'self' 'unsafe-inline' vercel.live", + "img-src 'self' data: blob: vercel.live vercel.com", + "font-src 'self' data: vercel.live assets.vercel.com", + "connect-src 'self' plausible.io vitals.vercel-insights.com vercel.live wss://ws-us3.pusher.com", "worker-src 'self' blob:", "child-src 'self' blob:", + "frame-src 'self' vercel.live", "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'",