diff --git a/.changeset/olive-rings-repeat.md b/.changeset/olive-rings-repeat.md new file mode 100644 index 00000000000..891a7760cba --- /dev/null +++ b/.changeset/olive-rings-repeat.md @@ -0,0 +1,5 @@ +--- +'@clerk/nextjs': patch +--- + +Remove `https://images.clerkstage.dev` from the default `connect-src` Content Security Policy directive. It is a Clerk-internal storage host that no application connects to. Organization logos are served from `https://img.clerk.com`, which stays in the default. diff --git a/packages/nextjs/src/server/__tests__/content-security-policy.test.ts b/packages/nextjs/src/server/__tests__/content-security-policy.test.ts index 6952292cf76..e4a23504f35 100644 --- a/packages/nextjs/src/server/__tests__/content-security-policy.test.ts +++ b/packages/nextjs/src/server/__tests__/content-security-policy.test.ts @@ -31,7 +31,7 @@ describe('CSP Header Utils', () => { expect(directives).toContainEqual("default-src 'self'"); expect(directives).toContainEqual( - "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com", + "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com", ); expect(directives).toContainEqual("form-action 'self'"); expect(directives).toContainEqual( @@ -116,7 +116,7 @@ describe('CSP Header Utils', () => { const directives = headerValue.split('; '); expect(directives).toContainEqual("default-src 'self'"); expect(directives).toContainEqual( - "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com", + "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com", ); expect(directives).toContainEqual("form-action 'self'"); expect(directives).toContainEqual( @@ -265,7 +265,7 @@ describe('CSP Header Utils', () => { const directives = result.headers[0][1].split('; '); expect(directives).toContainEqual( - `connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com https://api.example.com`, + `connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com https://api.example.com`, ); const imgSrcDirective = directives.find(d => d.startsWith('img-src')) || ''; @@ -285,7 +285,7 @@ describe('CSP Header Utils', () => { const directives = result.headers[0][1].split('; '); expect(directives).toContainEqual( - "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com", + "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com", ); expect(directives).toContainEqual("default-src 'self'"); expect(directives).toContainEqual("form-action 'self'"); @@ -331,7 +331,7 @@ describe('CSP Header Utils', () => { const directives = result.headers[0][1].split('; '); expect(directives).toContainEqual( - `connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com`, + `connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com`, ); expect(directives).toContainEqual(`img-src 'self' https://img.clerk.com`); expect(directives).toContainEqual( @@ -397,7 +397,7 @@ describe('CSP Header Utils', () => { const directives = result.headers[0][1].split('; '); expect(directives).toContainEqual( - "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://images.clerkstage.dev https://*.protect.clerk.com:* clerk.example.com", + "connect-src 'self' https://clerk-telemetry.com https://*.clerk-telemetry.com https://api.stripe.com https://maps.googleapis.com https://img.clerk.com https://*.protect.clerk.com:* clerk.example.com", ); expect(directives).toContainEqual("default-src 'self'"); expect(directives).toContainEqual("form-action 'self'"); diff --git a/packages/nextjs/src/server/content-security-policy.ts b/packages/nextjs/src/server/content-security-policy.ts index 88b120b2caf..82363698d07 100644 --- a/packages/nextjs/src/server/content-security-policy.ts +++ b/packages/nextjs/src/server/content-security-policy.ts @@ -106,7 +106,6 @@ class ContentSecurityPolicyDirectiveManager { 'https://api.stripe.com', 'https://maps.googleapis.com', 'https://img.clerk.com', - 'https://images.clerkstage.dev', clerkProtectionConnectOrigin, ], 'default-src': ['self'],