diff --git a/nginx.conf b/nginx.conf index 05258b42f..9774afca3 100644 --- a/nginx.conf +++ b/nginx.conf @@ -8,7 +8,7 @@ server { gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # Security headers - add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' https://*.jam.dev; worker-src 'self' blob:; frame-src 'self' https://accounts.google.com https://*.jam.dev; connect-src 'self' https://uziwdtkzofptihahfooo.supabase.co https://*.supabase.co https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com https://r.jina.ai https://s.jina.ai https://oauth2.googleapis.com https://www.googleapis.com https://*.ingest.sentry.io https://*.sentry.io https://eu.i.posthog.com https://*.posthog.com;" always; + add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' https://*.jam.dev; worker-src 'self' blob:; frame-src 'self' https://accounts.google.com https://*.jam.dev; connect-src 'self' https://*.jam.dev https://uziwdtkzofptihahfooo.supabase.co https://*.supabase.co https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com https://r.jina.ai https://s.jina.ai https://oauth2.googleapis.com https://www.googleapis.com https://*.ingest.sentry.io https://*.sentry.io https://eu.i.posthog.com https://*.posthog.com;" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; diff --git a/src/lib/observability.ts b/src/lib/observability.ts index 2b368ebe1..83f3f1400 100644 --- a/src/lib/observability.ts +++ b/src/lib/observability.ts @@ -102,7 +102,8 @@ export function initializeObservability(): void { dsn: sentryDsn, environment: import.meta.env.MODE, ignoreErrors: [/^Synthetic observability verification$/], - sendDefaultPii: false, + // No sendDefaultPii: deprecated, and Sentry ignores it whenever + // dataCollection is set. The block below is the only PII control. beforeBreadcrumb: filterObservabilityBreadcrumb, dataCollection: { userInfo: false, diff --git a/src/test/observability.test.ts b/src/test/observability.test.ts index 62a13a20a..9f779e46e 100644 --- a/src/test/observability.test.ts +++ b/src/test/observability.test.ts @@ -210,7 +210,6 @@ describe("observability primitives", () => { expect(sentryInitMock).toHaveBeenCalledWith(expect.objectContaining({ dsn: "https://public-test@sentry.example/1", ignoreErrors: [/^Synthetic observability verification$/], - sendDefaultPii: false, beforeBreadcrumb: filterObservabilityBreadcrumb, dataCollection: { userInfo: false, @@ -228,6 +227,9 @@ describe("observability primitives", () => { replaysSessionSampleRate: 0, replaysOnErrorSampleRate: 1, })); + // Deprecated and ignored whenever dataCollection is set: passing it would + // read as a PII control that does nothing. + expect(sentryInitMock.mock.calls[0][0]).not.toHaveProperty("sendDefaultPii"); expect(browserTracingIntegrationMock).toHaveBeenCalledOnce(); expect(replayIntegrationMock).toHaveBeenCalledWith({ maskAllText: true, diff --git a/src/test/vercel-deployment-config.test.ts b/src/test/vercel-deployment-config.test.ts index c3d6ac90c..6cfe5266f 100644 --- a/src/test/vercel-deployment-config.test.ts +++ b/src/test/vercel-deployment-config.test.ts @@ -99,6 +99,8 @@ describe("Vercel frontend deployment configuration", () => { expect(csp).toContain("script-src 'self' https://*.jam.dev"); expect(csp).toContain("frame-src 'self' https://accounts.google.com https://*.jam.dev"); + // Loading the recorder is useless if it cannot upload the capture. + expect(csp).toContain("connect-src 'self' https://*.jam.dev"); expect(nginxCsp).toBe(csp); expect(indexHtml).toContain(''); expect(indexHtml).not.toContain(''); diff --git a/vercel.json b/vercel.json index f4d864b3c..343b031a9 100644 --- a/vercel.json +++ b/vercel.json @@ -15,7 +15,7 @@ "headers": [ { "key": "Content-Security-Policy", - "value": "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' https://*.jam.dev; worker-src 'self' blob:; frame-src 'self' https://accounts.google.com https://*.jam.dev; connect-src 'self' https://uziwdtkzofptihahfooo.supabase.co https://*.supabase.co https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com https://r.jina.ai https://s.jina.ai https://oauth2.googleapis.com https://www.googleapis.com https://*.ingest.sentry.io https://*.sentry.io https://eu.i.posthog.com https://*.posthog.com;" + "value": "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data: https:; font-src 'self' data: https://fonts.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' https://*.jam.dev; worker-src 'self' blob:; frame-src 'self' https://accounts.google.com https://*.jam.dev; connect-src 'self' https://*.jam.dev https://uziwdtkzofptihahfooo.supabase.co https://*.supabase.co https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com https://r.jina.ai https://s.jina.ai https://oauth2.googleapis.com https://www.googleapis.com https://*.ingest.sentry.io https://*.sentry.io https://eu.i.posthog.com https://*.posthog.com;" }, { "key": "X-Frame-Options",