csp.ts 7.4 KB

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