import { NextRequest } from "next/server"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { proxy } from "./proxy"; function response(headers: Record = {}) { return proxy(new NextRequest("http://localhost:3000/setup", { headers })); } describe("deployment-aware content security policy", () => { beforeEach(() => { vi.stubEnv("NODE_ENV", "production"); vi.stubEnv("MAGENT_APPLICATION_URL", undefined); vi.stubEnv("MAGENT_RUNTIME_MANAGED", undefined); }); afterEach(() => vi.unstubAllEnvs()); it("keeps HTTPS upgrades enabled by default", () => { expect(response().headers.get("Content-Security-Policy")).toContain("upgrade-insecure-requests"); }); it("keeps HTTPS upgrades for an explicitly configured HTTPS site", () => { vi.stubEnv("MAGENT_APPLICATION_URL", "https://magent.example.com"); expect(response().headers.get("Content-Security-Policy")).toContain("upgrade-insecure-requests"); }); it("allows an unclaimed managed install to load its wizard on HTTP", () => { vi.stubEnv("MAGENT_RUNTIME_MANAGED", "1"); expect(response().headers.get("Content-Security-Policy")).not.toContain("upgrade-insecure-requests"); }); it.each(["0", "true", "false", ""])('does not activate managed setup for flag "%s"', (flag) => { vi.stubEnv("MAGENT_RUNTIME_MANAGED", flag); expect(response().headers.get("Content-Security-Policy")).toContain("upgrade-insecure-requests"); }); it.each(["https://magent.example.com", "not-a-url", "http://magent.lan/path"])( "does not let managed mode bypass configured HTTPS or invalid origins: %s", (origin) => { vi.stubEnv("MAGENT_RUNTIME_MANAGED", "1"); vi.stubEnv("MAGENT_APPLICATION_URL", origin); expect(response().headers.get("Content-Security-Policy")).toContain("upgrade-insecure-requests"); }, ); it("does not accept a caller-provided managed-mode header", () => { expect(response({ MAGENT_RUNTIME_MANAGED: "1" }).headers.get("Content-Security-Policy")).toContain( "upgrade-insecure-requests", ); }); it.each(["http://192.0.2.10:3000", "http://magent.lan:3000/", "http://[fd00::10]:3000"])( "supports the operator's explicit HTTP origin %s without upgrading its assets", (origin) => { vi.stubEnv("MAGENT_APPLICATION_URL", origin); expect(response().headers.get("Content-Security-Policy")).not.toContain("upgrade-insecure-requests"); }, ); it.each([ "", "not-a-url", "http:/magent.lan", "//magent.lan", "ftp://magent.lan", "http://user:password@magent.lan", "http://magent.lan/path", "http://magent.lan?query=1", "http://magent.lan#fragment", "http://magent.lan\\path", "http://magent.\tlan", ])("does not relax HTTPS upgrades for invalid or non-origin configuration %j", (origin) => { vi.stubEnv("MAGENT_APPLICATION_URL", origin); expect(response().headers.get("Content-Security-Policy")).toContain("upgrade-insecure-requests"); }); it("does not trust caller-controlled host or forwarding headers to disable upgrades", () => { const policy = response({ Host: "magent.lan:3000", "X-Forwarded-Host": "magent.lan:3000", "X-Forwarded-Proto": "http", Forwarded: "host=magent.lan:3000;proto=http", }).headers.get("Content-Security-Policy"); expect(policy).toContain("upgrade-insecure-requests"); }); it("preserves nonce propagation and strict production script rules on HTTP", () => { vi.stubEnv("MAGENT_APPLICATION_URL", "http://magent.lan:3000"); const first = response(); const policy = first.headers.get("Content-Security-Policy"); const nonce = first.headers.get("x-middleware-request-x-nonce"); expect(nonce).toBeTruthy(); expect(policy).toContain(`script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`); expect(policy).not.toContain("'unsafe-eval'"); expect(policy).toContain("frame-ancestors 'none'"); expect(policy).toContain("form-action 'self'"); expect(policy).toContain("connect-src 'self'"); expect(first.headers.get("x-middleware-request-content-security-policy")).toBe(policy); expect(response().headers.get("x-middleware-request-x-nonce")).not.toBe(nonce); }); });