From aec2373cbaff80cccf1b25113d99dfc653d903c7 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:47:39 +0100 Subject: [PATCH 1/3] fix(web): add baseline security response headers --- apps/web/next.config.mjs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 6263778e4a..f4c436ab12 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -79,6 +79,31 @@ const nextConfig = { }, ].filter(Boolean), }, + async headers() { + return [ + { + source: "/:path*", + headers: [ + { + key: "X-Content-Type-Options", + value: "nosniff", + }, + { + key: "Referrer-Policy", + value: "strict-origin-when-cross-origin", + }, + { + key: "X-DNS-Prefetch-Control", + value: "on", + }, + { + key: "Strict-Transport-Security", + value: "max-age=63072000; includeSubDomains", + }, + ], + }, + ]; + }, async rewrites() { return [ { From 883f344c9734f4240287f329b4e0d2f2ea82bafd Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:13:10 +0100 Subject: [PATCH 2/3] fix(web): scope X-Frame-Options to app routes and disable DNS prefetch --- apps/web/next.config.mjs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index f4c436ab12..a1eaa09e8a 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -94,7 +94,7 @@ const nextConfig = { }, { key: "X-DNS-Prefetch-Control", - value: "on", + value: "off", }, { key: "Strict-Transport-Security", @@ -102,6 +102,26 @@ const nextConfig = { }, ], }, + // Clickjacking protection for the authenticated/interactive app + // surfaces only. Shared videos (/s, /embed) and public collections + // (/c) are intentionally embeddable, so X-Frame-Options is NOT applied + // to them. + { + source: "/dashboard/:path*", + headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], + }, + { + source: "/onboarding/:path*", + headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], + }, + { + source: "/login", + headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], + }, + { + source: "/signup", + headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], + }, ]; }, async rewrites() { From 799e004339dc090bd66e27d26f927078e7f0c4c5 Mon Sep 17 00:00:00 2001 From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:51:10 +0100 Subject: [PATCH 3/3] fix(web): extend clickjacking protection to admin, verify-otp and auth subpaths --- apps/web/next.config.mjs | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index a1eaa09e8a..8f3c914239 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -103,25 +103,20 @@ const nextConfig = { ], }, // Clickjacking protection for the authenticated/interactive app - // surfaces only. Shared videos (/s, /embed) and public collections - // (/c) are intentionally embeddable, so X-Frame-Options is NOT applied - // to them. - { - source: "/dashboard/:path*", - headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], - }, - { - source: "/onboarding/:path*", + // surfaces (including subpaths). Shared videos (/s, /embed) and public + // collections (/c) are intentionally embeddable, so X-Frame-Options is + // NOT applied to them. + ...[ + "/dashboard/:path*", + "/onboarding/:path*", + "/admin/:path*", + "/verify-otp/:path*", + "/login/:path*", + "/signup/:path*", + ].map((source) => ({ + source, headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], - }, - { - source: "/login", - headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], - }, - { - source: "/signup", - headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }], - }, + })), ]; }, async rewrites() {