From 2453d3805b4d8eafcfdad05bdfe98823eb1ccb9e Mon Sep 17 00:00:00 2001 From: Adam Bilsing Date: Wed, 4 Sep 2024 22:53:15 -0500 Subject: [PATCH] CPX-632: add CSP in middleware --- src/app/layout.tsx | 4 ++-- src/middleware.ts | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ffe2f24..fbef143 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -31,7 +31,7 @@ export default function RootLayout({ }; const { storeHash } = useAppContext(); - const allowedParents = () => [ + const frameAncestors = [ `https://store-${storeHash}.mybigcommerce.com`, `https://store-${storeHash}.my-staging.com`, `https://store-${storeHash}.my-integration.com` @@ -42,7 +42,7 @@ export default function RootLayout({ + frame-ancestors={frameAncestors} /> diff --git a/src/middleware.ts b/src/middleware.ts index 662c8fd..5230871 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -17,7 +17,34 @@ export async function middleware(request: NextRequest) { return new NextResponse('invalid csrf token', { status: 403 }); } - return response; + const nonce = Buffer.from(crypto.randomUUID()).toString('base64'); + const cspHeader = ` + script-src 'self' 'nonce-${nonce}' 'strict-dynamic'; + frame-ancestors: 'https://store-*.mybigcommerce.com' 'https://store-*.my-integration.zone' 'https://store-*.my-staging.zone'; + `; + 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 newResponse = NextResponse.next({ + request: { + headers: requestHeaders, + }, + }) + newResponse.headers.set( + 'Content-Security-Policy', + contentSecurityPolicyHeaderValue + ) + + return newResponse } export const config = {