@@ -6,6 +6,26 @@ const withBundleAnalyzer = NextBundleAnalyzer({
66 enabled : process . env . ANALYZE === 'true' ,
77} )
88
9+ /**
10+ * CSP headers
11+ * img-src https to allow loading images from SSO providers
12+ */
13+ const cspHeader = `
14+ default-src 'self' https: wss:;
15+ script-src 'self' 'unsafe-eval' 'unsafe-inline' https:;
16+ style-src 'self' 'unsafe-inline' https:;
17+ img-src 'self' https: blob: data:;
18+ font-src 'self' https:;
19+ frame-src 'self' https:;
20+ worker-src 'self' blob:;
21+ object-src 'none';
22+ base-uri 'self';
23+ form-action 'self';
24+ frame-ancestors 'none';
25+ upgrade-insecure-requests;
26+ block-all-mixed-content;
27+ ` ;
28+
929// nextra config
1030const withNextra = nextra ( {
1131 theme : 'nextra-theme-docs' ,
@@ -36,6 +56,40 @@ const nextraConfig = withNextra({
3656 } ,
3757 ] ,
3858 } ,
59+ headers ( ) {
60+ return [
61+ {
62+ source : "/:path*" ,
63+ headers : [
64+ {
65+ key : "x-frame-options" ,
66+ value : "SAMEORIGIN" ,
67+ } ,
68+ {
69+ key : "X-Content-Type-Options" ,
70+ value : "nosniff" ,
71+ } ,
72+ {
73+ key : "Referrer-Policy" ,
74+ value : "strict-origin-when-cross-origin" ,
75+ } ,
76+ {
77+ key : "Permissions-Policy" ,
78+ value : "autoplay=*, fullscreen=*, microphone=*" ,
79+ } ,
80+ ] ,
81+ } ,
82+ {
83+ source : "/:path((?!api).*)*" ,
84+ headers : [
85+ {
86+ key : "Content-Security-Policy" ,
87+ value : cspHeader . replace ( / \n / g, "" ) ,
88+ } ,
89+ ] ,
90+ } ,
91+ ]
92+ } ,
3993 redirects : async ( ) => [
4094 ...nonPermanentRedirects . map ( ( [ source , destination ] ) => ( {
4195 source,
0 commit comments