Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

middleware.ts 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import type { NextRequest } from 'next/server'
  2. import { NextResponse } from 'next/server'
  3. 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'
  4. const wrapResponseWithXFrameOptions = (response: NextResponse, pathname: string) => {
  5. // prevent clickjacking: https://owasp.org/www-community/attacks/Clickjacking
  6. // Chatbot page should be allowed to be embedded in iframe. It's a feature
  7. if (process.env.NEXT_PUBLIC_ALLOW_EMBED !== 'true' && !pathname.startsWith('/chat') && !pathname.startsWith('/workflow') && !pathname.startsWith('/completion') && !pathname.startsWith('/webapp-signin'))
  8. response.headers.set('X-Frame-Options', 'DENY')
  9. return response
  10. }
  11. export function middleware(request: NextRequest) {
  12. const { pathname } = request.nextUrl
  13. const requestHeaders = new Headers(request.headers)
  14. const response = NextResponse.next({
  15. request: {
  16. headers: requestHeaders,
  17. },
  18. })
  19. const isWhiteListEnabled = !!process.env.NEXT_PUBLIC_CSP_WHITELIST && process.env.NODE_ENV === 'production'
  20. if (!isWhiteListEnabled)
  21. return wrapResponseWithXFrameOptions(response, pathname)
  22. const whiteList = `${process.env.NEXT_PUBLIC_CSP_WHITELIST} ${NECESSARY_DOMAIN}`
  23. const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  24. const csp = `'nonce-${nonce}'`
  25. const scheme_source = 'data: mediastream: blob: filesystem:'
  26. const cspHeader = `
  27. default-src 'self' ${scheme_source} ${csp} ${whiteList};
  28. connect-src 'self' ${scheme_source} ${csp} ${whiteList};
  29. script-src 'self' ${scheme_source} ${csp} ${whiteList};
  30. style-src 'self' 'unsafe-inline' ${scheme_source} ${whiteList};
  31. worker-src 'self' ${scheme_source} ${csp} ${whiteList};
  32. media-src 'self' ${scheme_source} ${csp} ${whiteList};
  33. img-src * data: blob:;
  34. font-src 'self';
  35. object-src 'none';
  36. base-uri 'self';
  37. form-action 'self';
  38. upgrade-insecure-requests;
  39. `
  40. // Replace newline characters and spaces
  41. const contentSecurityPolicyHeaderValue = cspHeader
  42. .replace(/\s{2,}/g, ' ')
  43. .trim()
  44. requestHeaders.set('x-nonce', nonce)
  45. requestHeaders.set(
  46. 'Content-Security-Policy',
  47. contentSecurityPolicyHeaderValue,
  48. )
  49. return wrapResponseWithXFrameOptions(response, pathname)
  50. }
  51. export const config = {
  52. matcher: [
  53. /*
  54. * Match all request paths except for the ones starting with:
  55. * - api (API routes)
  56. * - _next/static (static files)
  57. * - _next/image (image optimization files)
  58. * - favicon.ico (favicon file)
  59. */
  60. {
  61. // source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
  62. source: '/((?!_next/static|_next/image|favicon.ico).*)',
  63. // source: '/(.*)',
  64. // missing: [
  65. // { type: 'header', key: 'next-router-prefetch' },
  66. // { type: 'header', key: 'purpose', value: 'prefetch' },
  67. // ],
  68. },
  69. ],
  70. }