diff --git a/src/headers/content-security-policy.ts b/src/headers/content-security-policy.ts index 25de496..481e8fd 100644 --- a/src/headers/content-security-policy.ts +++ b/src/headers/content-security-policy.ts @@ -76,13 +76,18 @@ export const contentSecurityPolicy = ( ]; if (typeof value === "boolean") { - return `${directive}`; + if (value) { + return `${directive}`; + } + + return ""; } const directiveValue = Array.isArray(value) ? value.join(" ") : value; return `${directive} ${directiveValue}`; }) + .filter(Boolean) .join(";"); context.response.headers.set("Content-Security-Policy", header); diff --git a/tests/headers/content-security-policy.test.ts b/tests/headers/content-security-policy.test.ts index 83b7e81..e50fec9 100644 --- a/tests/headers/content-security-policy.test.ts +++ b/tests/headers/content-security-policy.test.ts @@ -19,6 +19,28 @@ beforeAll(() => { context.text(StatusCode.OK, "Hello, World!"); }); + server.app.get("/upgrade-insecure-requests/true", (context) => { + contentSecurityPolicy(context, { + directives: { + defaultSrc: ["'self'"], + upgradeInsecureRequests: true, + }, + }); + + context.text(StatusCode.OK, "Hello, World!"); + }); + + server.app.get("/upgrade-insecure-requests/false", (context) => { + contentSecurityPolicy(context, { + directives: { + defaultSrc: ["'self'"], + upgradeInsecureRequests: false, + }, + }); + + context.text(StatusCode.OK, "Hello, World!"); + }); + server.start(); }); @@ -39,4 +61,36 @@ describe("headers - content-security-policy", () => { "default-src 'self';script-src 'self' https://example.com", ); }); + + it("should set security headers with upgrade-insecure-requests", async () => { + const response = await fetch( + server.url("/upgrade-insecure-requests/true"), + { + method: "GET", + }, + ); + + // drain response to ensure no memory leak + await response.text(); + + expect(response.headers.get("Content-Security-Policy")).toEqual( + "default-src 'self';upgrade-insecure-requests", + ); + }); + + it("should not set security headers with upgrade-insecure-requests", async () => { + const response = await fetch( + server.url("/upgrade-insecure-requests/false"), + { + method: "GET", + }, + ); + + // drain response to ensure no memory leak + await response.text(); + + expect(response.headers.get("Content-Security-Policy")).toEqual( + "default-src 'self'", + ); + }); });