From 234a2aaf1d606f0b02a6f6aadb98fbcd0169e3c8 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 21 Sep 2026 20:42:26 +0200 Subject: [PATCH] security: implement dynamic Content Security Policy (CSP) - Create src/middleware.ts for per-request nonce-based CSP - Integrate src/lib/csp.ts to build the CSP header dynamically - Add src/middleware.test.ts to verify CSP header is set with nonce - Biome lint and TypeScript checks pass --- src/middleware.test.ts | 16 ++++++++++++++++ src/middleware.ts | 14 ++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/middleware.test.ts create mode 100644 src/middleware.ts diff --git a/src/middleware.test.ts b/src/middleware.test.ts new file mode 100644 index 00000000..d8720f6f --- /dev/null +++ b/src/middleware.test.ts @@ -0,0 +1,16 @@ +import { NextRequest } from "next/server"; +import { describe, expect, it } from "vitest"; +import { middleware } from "./middleware"; + +describe("middleware", () => { + it("sets Content-Security-Policy header on the response", async () => { + const request = new NextRequest("https://example.com/test"); + const response = await middleware(request); + + const csp = response.headers.get("Content-Security-Policy"); + expect(csp).toBeDefined(); + expect(csp).toContain("default-src 'self'"); + expect(csp).toContain("script-src 'self'"); + expect(csp).toContain("nonce-"); + }); +}); diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 00000000..187ca1fc --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,14 @@ +import type { NextRequest } from "next/server"; +import { NextResponse } from "next/server"; +import { buildContentSecurityPolicy } from "./lib/csp"; + +export async function middleware(_request: NextRequest) { + const nonce = crypto.randomUUID(); // Or a more robust nonce generation if needed + + const csp = buildContentSecurityPolicy(nonce); + + const response = NextResponse.next(); + response.headers.set("Content-Security-Policy", csp); + + return response; +}