Skip to content

Commit e2d4d0e

Browse files
authored
feat(security): add GTM and GA domains to CSP for hosted environments (#4024)
* feat(security): add GTM and GA domains to CSP for hosted environments * lint
1 parent cd3cb87 commit e2d4d0e

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

apps/sim/lib/core/security/csp.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ vi.mock('@/lib/core/config/env', () =>
1919

2020
vi.mock('@/lib/core/config/feature-flags', () => ({
2121
isDev: false,
22+
isHosted: false,
2223
isReactGrabEnabled: false,
2324
}))
2425

apps/sim/lib/core/security/csp.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { env, getEnv } from '../config/env'
2-
import { isDev, isReactGrabEnabled } from '../config/feature-flags'
2+
import { isDev, isHosted, isReactGrabEnabled } from '../config/feature-flags'
33

44
/**
55
* Content Security Policy (CSP) configuration builder
@@ -42,6 +42,7 @@ export const buildTimeCSPDirectives: CSPDirectives = {
4242
'https://assets.onedollarstats.com',
4343
'https://challenges.cloudflare.com',
4444
...(isReactGrabEnabled ? ['https://unpkg.com'] : []),
45+
...(isHosted ? ['https://www.googletagmanager.com', 'https://www.google-analytics.com'] : []),
4546
],
4647

4748
'style-src': ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
@@ -59,6 +60,7 @@ export const buildTimeCSPDirectives: CSPDirectives = {
5960
'https://s3.amazonaws.com',
6061
'https://github.com/*',
6162
'https://collector.onedollarstats.com',
63+
...(isHosted ? ['https://www.googletagmanager.com', 'https://www.google-analytics.com'] : []),
6264
...(env.S3_BUCKET_NAME && env.AWS_REGION
6365
? [`https://${env.S3_BUCKET_NAME}.s3.${env.AWS_REGION}.amazonaws.com`]
6466
: []),
@@ -105,6 +107,13 @@ export const buildTimeCSPDirectives: CSPDirectives = {
105107
'https://github.com/*',
106108
'https://challenges.cloudflare.com',
107109
'https://collector.onedollarstats.com',
110+
...(isHosted
111+
? [
112+
'https://www.googletagmanager.com',
113+
'https://*.google-analytics.com',
114+
'https://*.analytics.google.com',
115+
]
116+
: []),
108117
...getHostnameFromUrl(env.NEXT_PUBLIC_BRAND_LOGO_URL),
109118
...getHostnameFromUrl(env.NEXT_PUBLIC_PRIVACY_URL),
110119
...getHostnameFromUrl(env.NEXT_PUBLIC_TERMS_URL),
@@ -116,6 +125,7 @@ export const buildTimeCSPDirectives: CSPDirectives = {
116125
'https://drive.google.com',
117126
'https://docs.google.com',
118127
'https://*.google.com',
128+
...(isHosted ? ['https://www.googletagmanager.com'] : []),
119129
],
120130

121131
'frame-ancestors': ["'self'"],
@@ -171,16 +181,24 @@ export function generateRuntimeCSP(): string {
171181
const brandLogoDomain = brandLogoDomains[0] || ''
172182
const brandFaviconDomain = brandFaviconDomains[0] || ''
173183
const reactGrabScript = isReactGrabEnabled ? 'https://unpkg.com' : ''
184+
const gtmScript = isHosted
185+
? 'https://www.googletagmanager.com https://www.google-analytics.com'
186+
: ''
187+
const gtmConnect = isHosted
188+
? 'https://www.googletagmanager.com https://*.google-analytics.com https://*.analytics.google.com'
189+
: ''
190+
const gtmImg = isHosted ? 'https://www.googletagmanager.com https://www.google-analytics.com' : ''
191+
const gtmFrame = isHosted ? 'https://www.googletagmanager.com' : ''
174192

175193
return `
176194
default-src 'self';
177-
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://assets.onedollarstats.com https://challenges.cloudflare.com ${reactGrabScript};
195+
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://assets.onedollarstats.com https://challenges.cloudflare.com ${reactGrabScript} ${gtmScript};
178196
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
179-
img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com https://*.githubusercontent.com https://*.s3.amazonaws.com https://s3.amazonaws.com https://*.amazonaws.com https://*.blob.core.windows.net https://github.com/* https://collector.onedollarstats.com ${brandLogoDomain} ${brandFaviconDomain};
197+
img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com https://*.githubusercontent.com https://*.s3.amazonaws.com https://s3.amazonaws.com https://*.amazonaws.com https://*.blob.core.windows.net https://github.com/* https://collector.onedollarstats.com ${gtmImg} ${brandLogoDomain} ${brandFaviconDomain};
180198
media-src 'self' blob:;
181199
font-src 'self' https://fonts.gstatic.com;
182-
connect-src 'self' ${appUrl} ${ollamaUrl} ${socketUrl} ${socketWsUrl} https://api.browser-use.com https://api.exa.ai https://api.firecrawl.dev https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.blob.core.windows.net https://api.github.com https://github.com/* https://*.atlassian.com https://*.supabase.co https://challenges.cloudflare.com https://collector.onedollarstats.com ${dynamicDomainsStr};
183-
frame-src 'self' https://challenges.cloudflare.com https://drive.google.com https://docs.google.com https://*.google.com;
200+
connect-src 'self' ${appUrl} ${ollamaUrl} ${socketUrl} ${socketWsUrl} https://api.browser-use.com https://api.exa.ai https://api.firecrawl.dev https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.blob.core.windows.net https://api.github.com https://github.com/* https://*.atlassian.com https://*.supabase.co https://challenges.cloudflare.com https://collector.onedollarstats.com ${gtmConnect} ${dynamicDomainsStr};
201+
frame-src 'self' https://challenges.cloudflare.com https://drive.google.com https://docs.google.com https://*.google.com ${gtmFrame};
184202
frame-ancestors 'self';
185203
form-action 'self';
186204
base-uri 'self';

0 commit comments

Comments
 (0)