| | import type { NextRequest } from 'next/server' |
| | import { NextResponse } from 'next/server' |
| |
|
| | const NECESSARY_DOMAIN = '*.sentry.io http://localhost:* http://127.0.0.1:* https://analytics.google.com googletagmanager.com *.googletagmanager.com https://www.google-analytics.com https://api.github.com' |
| |
|
| | export function middleware(request: NextRequest) { |
| | const isWhiteListEnabled = !!process.env.NEXT_PUBLIC_CSP_WHITELIST && process.env.NODE_ENV === 'production' |
| | if (!isWhiteListEnabled) |
| | return NextResponse.next() |
| |
|
| | const whiteList = `${process.env.NEXT_PUBLIC_CSP_WHITELIST} ${NECESSARY_DOMAIN}` |
| | const nonce = Buffer.from(crypto.randomUUID()).toString('base64') |
| | const csp = `'nonce-${nonce}'` |
| |
|
| | const scheme_source = 'data: mediastream: blob: filesystem:' |
| |
|
| | const cspHeader = ` |
| | default-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | connect-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | script-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | style-src 'self' 'unsafe-inline' ${scheme_source} ${whiteList}; |
| | worker-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | media-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | img-src 'self' ${scheme_source} ${csp} ${whiteList}; |
| | font-src 'self'; |
| | object-src 'none'; |
| | base-uri 'self'; |
| | form-action 'self'; |
| | upgrade-insecure-requests; |
| | ` |
| | |
| | const contentSecurityPolicyHeaderValue = cspHeader |
| | .replace(/\s{2,}/g, ' ') |
| | .trim() |
| |
|
| | const requestHeaders = new Headers(request.headers) |
| | requestHeaders.set('x-nonce', nonce) |
| |
|
| | requestHeaders.set( |
| | 'Content-Security-Policy', |
| | contentSecurityPolicyHeaderValue, |
| | ) |
| |
|
| | const response = NextResponse.next({ |
| | request: { |
| | headers: requestHeaders, |
| | }, |
| | }) |
| | response.headers.set( |
| | 'Content-Security-Policy', |
| | contentSecurityPolicyHeaderValue, |
| | ) |
| |
|
| | return response |
| | } |
| |
|
| | export const config = { |
| | matcher: [ |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | { |
| | |
| | source: '/((?!_next/static|_next/image|favicon.ico).*)', |
| | |
| | |
| | |
| | |
| | |
| | }, |
| | ], |
| | } |
| |
|