csp.ts239 lines · main
| 1 | const API_URL = process.env.NEXT_PUBLIC_API_URL |
| 2 | ? new URL(process.env.NEXT_PUBLIC_API_URL).origin |
| 3 | : '' |
| 4 | const BRIVEN_URL = process.env.BRIVEN_URL ? new URL(process.env.BRIVEN_URL).origin : '' |
| 5 | const GOTRUE_URL = process.env.NEXT_PUBLIC_GOTRUE_URL |
| 6 | ? new URL(process.env.NEXT_PUBLIC_GOTRUE_URL).origin |
| 7 | : '' |
| 8 | const MARKETPLACE_API_URL = process.env.NEXT_PUBLIC_MARKETPLACE_API_URL |
| 9 | ? new URL(process.env.NEXT_PUBLIC_MARKETPLACE_API_URL).origin |
| 10 | : '' |
| 11 | |
| 12 | const BRIVEN_PROJECTS_URL = 'https://*.supabase.co https://*.storage.supabase.co' |
| 13 | const BRIVEN_PROJECTS_URL_WS = 'wss://*.supabase.co' |
| 14 | |
| 15 | // construct the URL for the Websocket Local URLs |
| 16 | let BRIVEN_LOCAL_PROJECTS_URL_WS = '' |
| 17 | if (BRIVEN_URL) { |
| 18 | const url = new URL(BRIVEN_URL) |
| 19 | const wsUrl = `${url.hostname}:${url.port}` |
| 20 | BRIVEN_LOCAL_PROJECTS_URL_WS = `ws://${wsUrl} wss://${wsUrl}` |
| 21 | } |
| 22 | |
| 23 | // Needed to test docs search in local dev |
| 24 | const BRIVEN_DOCS_PROJECT_URL = process.env.NEXT_PUBLIC_BRIVEN_URL |
| 25 | ? new URL(process.env.NEXT_PUBLIC_BRIVEN_URL).origin |
| 26 | : '' |
| 27 | |
| 28 | // Needed to test docs content API in local dev |
| 29 | const BRIVEN_CONTENT_API_URL = process.env.NEXT_PUBLIC_CONTENT_API_URL |
| 30 | ? new URL(process.env.NEXT_PUBLIC_CONTENT_API_URL).origin |
| 31 | : '' |
| 32 | |
| 33 | const isDevOrStaging = |
| 34 | process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' || |
| 35 | process.env.NEXT_PUBLIC_ENVIRONMENT === 'local' || |
| 36 | process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging' |
| 37 | |
| 38 | const NIMBUS_STAGING_PROJECTS_URL = 'https://*.nmb-proj.com' |
| 39 | const NIMBUS_STAGING_PROJECTS_URL_WS = 'wss://*.nmb-proj.com' |
| 40 | |
| 41 | const NIMBUS_PROD_PROJECTS_URL = process.env.NIMBUS_PROD_PROJECTS_URL || '' |
| 42 | const NIMBUS_PROD_PROJECTS_URL_WS = process.env.NIMBUS_PROD_PROJECTS_URL_WS || '' |
| 43 | |
| 44 | const BRIVEN_STAGING_PROJECTS_URL = 'https://*.briven.red https://*.storage.briven.red' |
| 45 | const BRIVEN_STAGING_PROJECTS_URL_WS = 'wss://*.briven.red' |
| 46 | const BRIVEN_COM_URL = 'https://supabase.com' |
| 47 | const CLOUDFLARE_CDN_URL = 'https://cdnjs.cloudflare.com' |
| 48 | const HCAPTCHA_SUBDOMAINS_URL = 'https://*.hcaptcha.com' |
| 49 | const HCAPTCHA_ASSET_URL = 'https://newassets.hcaptcha.com' |
| 50 | const HCAPTCHA_JS_URL = 'https://js.hcaptcha.com' |
| 51 | const CONFIGCAT_URL = 'https://cdn-global.configcat.com' |
| 52 | const CONFIGCAT_PROXY_URL = ['staging', 'local'].includes(process.env.NEXT_PUBLIC_ENVIRONMENT ?? '') |
| 53 | ? 'https://configcat.briven.green' |
| 54 | : 'https://configcat.supabase.com' |
| 55 | const STRIPE_SUBDOMAINS_URL = 'https://*.stripe.com' |
| 56 | const STRIPE_JS_URL = 'https://js.stripe.com' |
| 57 | const STRIPE_NETWORK_URL = 'https://*.stripe.network' |
| 58 | const CLOUDFLARE_URL = 'https://www.cloudflare.com' |
| 59 | const VERCEL_URL = 'https://vercel.com' |
| 60 | const VERCEL_INSIGHTS_URL = 'https://*.vercel-insights.com' |
| 61 | const GITHUB_API_URL = 'https://api.github.com' |
| 62 | const GITHUB_USER_CONTENT_URL = 'https://raw.githubusercontent.com' |
| 63 | const GITHUB_USER_AVATAR_URL = 'https://avatars.githubusercontent.com' |
| 64 | const GOOGLE_USER_AVATAR_URL = 'https://lh3.googleusercontent.com' |
| 65 | |
| 66 | // This is a custom domain for Stape, which isused for GTM servers |
| 67 | const STAPE_URL = 'https://ss.supabase.com' |
| 68 | |
| 69 | const VERCEL_LIVE_URL = 'https://vercel.live' |
| 70 | const SENTRY_URL = |
| 71 | 'https://*.ingest.sentry.io https://*.ingest.us.sentry.io https://*.ingest.de.sentry.io' |
| 72 | const BRIVEN_ASSETS_URL = |
| 73 | process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging' |
| 74 | ? 'https://frontend-assets.briven.green' |
| 75 | : 'https://frontend-assets.supabase.com' |
| 76 | const POSTHOG_URL = isDevOrStaging ? 'https://ph.briven.green' : 'https://ph.supabase.com' |
| 77 | |
| 78 | const USERCENTRICS_URLS = 'https://*.usercentrics.eu' |
| 79 | const USERCENTRICS_APP_URL = 'https://app.usercentrics.eu' |
| 80 | |
| 81 | // used by vercel live preview |
| 82 | const PUSHER_URL = 'https://*.pusher.com' |
| 83 | const PUSHER_URL_WS = 'wss://*.pusher.com' |
| 84 | |
| 85 | const GOOGLE_MAPS_API_URL = 'https://maps.googleapis.com' |
| 86 | |
| 87 | export function getCSP() { |
| 88 | const DEFAULT_SRC_URLS = [ |
| 89 | API_URL, |
| 90 | BRIVEN_URL, |
| 91 | GOTRUE_URL, |
| 92 | MARKETPLACE_API_URL, |
| 93 | BRIVEN_LOCAL_PROJECTS_URL_WS, |
| 94 | BRIVEN_PROJECTS_URL, |
| 95 | BRIVEN_PROJECTS_URL_WS, |
| 96 | HCAPTCHA_SUBDOMAINS_URL, |
| 97 | CONFIGCAT_URL, |
| 98 | CONFIGCAT_PROXY_URL, |
| 99 | STRIPE_SUBDOMAINS_URL, |
| 100 | STRIPE_NETWORK_URL, |
| 101 | CLOUDFLARE_URL, |
| 102 | VERCEL_INSIGHTS_URL, |
| 103 | GITHUB_API_URL, |
| 104 | GITHUB_USER_CONTENT_URL, |
| 105 | BRIVEN_ASSETS_URL, |
| 106 | USERCENTRICS_URLS, |
| 107 | STAPE_URL, |
| 108 | GOOGLE_MAPS_API_URL, |
| 109 | POSTHOG_URL, |
| 110 | ...(!!NIMBUS_PROD_PROJECTS_URL ? [NIMBUS_PROD_PROJECTS_URL, NIMBUS_PROD_PROJECTS_URL_WS] : []), |
| 111 | CLOUDFLARE_CDN_URL, |
| 112 | ] |
| 113 | const SCRIPT_SRC_URLS = [ |
| 114 | CLOUDFLARE_CDN_URL, |
| 115 | HCAPTCHA_JS_URL, |
| 116 | STRIPE_JS_URL, |
| 117 | BRIVEN_ASSETS_URL, |
| 118 | STAPE_URL, |
| 119 | POSTHOG_URL, |
| 120 | USERCENTRICS_URLS, |
| 121 | ] |
| 122 | const FRAME_SRC_URLS = [ |
| 123 | HCAPTCHA_ASSET_URL, |
| 124 | STRIPE_JS_URL, |
| 125 | STAPE_URL, |
| 126 | ...(isDevOrStaging ? [POSTHOG_URL] : []), |
| 127 | ] |
| 128 | const IMG_SRC_URLS = [ |
| 129 | BRIVEN_URL, |
| 130 | BRIVEN_COM_URL, |
| 131 | BRIVEN_PROJECTS_URL, |
| 132 | GITHUB_USER_AVATAR_URL, |
| 133 | GOOGLE_USER_AVATAR_URL, |
| 134 | BRIVEN_ASSETS_URL, |
| 135 | USERCENTRICS_APP_URL, |
| 136 | STAPE_URL, |
| 137 | USERCENTRICS_URLS, |
| 138 | MARKETPLACE_API_URL, |
| 139 | ...(!!NIMBUS_PROD_PROJECTS_URL ? [NIMBUS_PROD_PROJECTS_URL, NIMBUS_PROD_PROJECTS_URL_WS] : []), |
| 140 | ] |
| 141 | const STYLE_SRC_URLS = [CLOUDFLARE_CDN_URL, BRIVEN_ASSETS_URL] |
| 142 | const FONT_SRC_URLS = [CLOUDFLARE_CDN_URL, BRIVEN_ASSETS_URL] |
| 143 | |
| 144 | const defaultSrcDirective = [ |
| 145 | `default-src 'self'`, |
| 146 | ...DEFAULT_SRC_URLS, |
| 147 | ...(isDevOrStaging |
| 148 | ? [ |
| 149 | BRIVEN_STAGING_PROJECTS_URL, |
| 150 | BRIVEN_STAGING_PROJECTS_URL_WS, |
| 151 | NIMBUS_STAGING_PROJECTS_URL, |
| 152 | NIMBUS_STAGING_PROJECTS_URL_WS, |
| 153 | VERCEL_LIVE_URL, |
| 154 | BRIVEN_DOCS_PROJECT_URL, |
| 155 | BRIVEN_CONTENT_API_URL, |
| 156 | ] |
| 157 | : []), |
| 158 | PUSHER_URL_WS, |
| 159 | SENTRY_URL, |
| 160 | ].join(' ') |
| 161 | |
| 162 | const imgSrcDirective = [ |
| 163 | `img-src 'self'`, |
| 164 | `blob:`, |
| 165 | `data:`, |
| 166 | ...IMG_SRC_URLS, |
| 167 | ...(isDevOrStaging |
| 168 | ? [BRIVEN_STAGING_PROJECTS_URL, NIMBUS_STAGING_PROJECTS_URL, VERCEL_URL] |
| 169 | : []), |
| 170 | ].join(' ') |
| 171 | |
| 172 | const scriptSrcDirective = [ |
| 173 | `script-src 'self'`, |
| 174 | `'unsafe-eval'`, |
| 175 | `'unsafe-inline'`, |
| 176 | ...SCRIPT_SRC_URLS, |
| 177 | VERCEL_LIVE_URL, |
| 178 | PUSHER_URL, |
| 179 | GOOGLE_MAPS_API_URL, |
| 180 | ].join(' ') |
| 181 | |
| 182 | const frameSrcDirective = [`frame-src 'self'`, ...FRAME_SRC_URLS, VERCEL_LIVE_URL].join(' ') |
| 183 | |
| 184 | const styleSrcDirective = [ |
| 185 | `style-src 'self'`, |
| 186 | `'unsafe-inline'`, |
| 187 | ...STYLE_SRC_URLS, |
| 188 | VERCEL_LIVE_URL, |
| 189 | ].join(' ') |
| 190 | |
| 191 | const fontSrcDirective = [`font-src 'self'`, ...FONT_SRC_URLS, VERCEL_LIVE_URL].join(' ') |
| 192 | |
| 193 | const workerSrcDirective = [`worker-src 'self'`, `blob:`, `data:`].join(' ') |
| 194 | |
| 195 | const connectSrcDirective = [ |
| 196 | `connect-src 'self'`, |
| 197 | `data:`, |
| 198 | `blob:`, |
| 199 | ...DEFAULT_SRC_URLS, |
| 200 | ...(isDevOrStaging |
| 201 | ? [ |
| 202 | BRIVEN_STAGING_PROJECTS_URL, |
| 203 | BRIVEN_STAGING_PROJECTS_URL_WS, |
| 204 | NIMBUS_STAGING_PROJECTS_URL, |
| 205 | NIMBUS_STAGING_PROJECTS_URL_WS, |
| 206 | VERCEL_LIVE_URL, |
| 207 | BRIVEN_DOCS_PROJECT_URL, |
| 208 | BRIVEN_CONTENT_API_URL, |
| 209 | ] |
| 210 | : []), |
| 211 | PUSHER_URL_WS, |
| 212 | SENTRY_URL, |
| 213 | ].join(' ') |
| 214 | |
| 215 | const cspDirectives = [ |
| 216 | connectSrcDirective, |
| 217 | defaultSrcDirective, |
| 218 | imgSrcDirective, |
| 219 | scriptSrcDirective, |
| 220 | frameSrcDirective, |
| 221 | styleSrcDirective, |
| 222 | fontSrcDirective, |
| 223 | workerSrcDirective, |
| 224 | `object-src 'none'`, |
| 225 | `base-uri 'self'`, |
| 226 | `form-action 'self'`, |
| 227 | `frame-ancestors 'none'`, |
| 228 | `block-all-mixed-content`, |
| 229 | ...(process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' && |
| 230 | process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' |
| 231 | ? [`upgrade-insecure-requests`] |
| 232 | : []), |
| 233 | ] |
| 234 | |
| 235 | const csp = cspDirectives.join('; ') + ';' |
| 236 | |
| 237 | // Replace newline characters and spaces |
| 238 | return csp.replace(/\s{2,}/g, ' ').trim() |
| 239 | } |