From 440a4e919a0fca997e39a225e95397b63e35f30a Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sat, 18 Apr 2026 13:10:42 +0200 Subject: [PATCH] Revert "perf: make root HTML cacheable by dropping per-request CSP nonce" This reverts commit 522bf6a01946820e91c2528c1fbb65752ef94ad5. --- README.md | 2 +- app/[locale]/layout.tsx | 9 ++++++++- app/layout.tsx | 23 ++++++++++++++++++++++- components/providers/intl-provider.tsx | 1 + proxy.ts | 12 ++++++++++-- public/theme-init.js | 12 ------------ 6 files changed, 42 insertions(+), 17 deletions(-) delete mode 100644 public/theme-init.js diff --git a/README.md b/README.md index 90e79e64..0feff814 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Built with Next.js and the JMAP protocol. - **TOTP two-factor authentication** - **Account security panel** - manage passwords and 2FA via Stalwart admin API - **"Remember me"** - AES-256-GCM encrypted httpOnly cookie (opt-in) -- **Security headers** - enforced CSP (script-src 'self', no unsafe-inline), X-Frame-Options, Referrer-Policy; SSRF redirect validation; PDF iframe sandbox; IP spoofing prevention +- **Security headers** - enforced CSP with per-request nonce, X-Frame-Options, Referrer-Policy; SSRF redirect validation; PDF iframe sandbox; IP spoofing prevention - **Plugin hardening** - dangerous-pattern detection, admin approval required, secure HTTP proxy API (no auth-header exposure) - **Newsletter unsubscribe** (RFC 2369) diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx index 1bedc98c..12b1a4e3 100644 --- a/app/[locale]/layout.tsx +++ b/app/[locale]/layout.tsx @@ -18,8 +18,15 @@ export default async function LocaleLayout({ if (!(locales as readonly string[]).includes(locale)) notFound(); + let messages; + try { + messages = (await import(`@/locales/${locale}/common.json`)).default; + } catch { + notFound(); + } + return ( - + diff --git a/app/layout.tsx b/app/layout.tsx index 58c11fe6..c2a54606 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; +import { headers } from "next/headers"; import { getLocale } from "next-intl/server"; import { PWAInstallPrompt } from "@/components/pwa-install-prompt"; import { ServiceWorkerRegistration } from "@/components/service-worker-registration"; @@ -39,6 +40,7 @@ export default async function RootLayout({ children: React.ReactNode; }) { const locale = await getLocale(); + const nonce = (await headers()).get("x-nonce") ?? ""; const parentOrigin = process.env.NEXT_PUBLIC_PARENT_ORIGIN || ""; return ( @@ -55,7 +57,26 @@ export default async function RootLayout({ {parentOrigin && ( )} -