From 814d6de59088ca005aca075dbfebe5dadab7c67f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 27 Nov 2024 18:48:18 +0100 Subject: [PATCH 1/3] fix(error): strict security headers --- src/runtime/internal/error.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/runtime/internal/error.ts b/src/runtime/internal/error.ts index e84dba6021..d8997c5f50 100644 --- a/src/runtime/internal/error.ts +++ b/src/runtime/internal/error.ts @@ -1,5 +1,10 @@ // import ansiHTML from 'ansi-html' -import { send, setResponseHeader, setResponseStatus } from "h3"; +import { + send, + setResponseHeader, + setResponseHeaders, + setResponseStatus, +} from "h3"; import type { NitroErrorHandler } from "nitropack/types"; import { isJsonRequest, normalizeError } from "./utils"; @@ -56,6 +61,18 @@ export default defineNitroErrorHandler( setResponseHeader(event, "Cache-Control", "no-cache"); } + // Security headers + setResponseHeaders(event, { + // Disable the execution of any js + "Content-Security-Policy": "script-src 'none'; frame-ancestors 'none';", + // Prevent browser from guessing the MIME types of resources. + "X-Content-Type-Options": "nosniff", + // Prevent error page from being embedded in an iframe + "X-Frame-Options": "DENY", + // Prevent browsers from sending the Referer header + "Referrer-Policy": "no-referrer", + }); + setResponseStatus(event, statusCode, statusMessage); if (isJsonRequest(event)) { From 3a8e6fd5a62b8a9ea41261be0a74510102d5f6db Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 27 Nov 2024 18:56:08 +0100 Subject: [PATCH 2/3] add test --- test/tests.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/tests.ts b/test/tests.ts index 4f2aec0dc4..d73aeb0150 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -378,13 +378,21 @@ export function testNitro( }); it("handles errors", async () => { - const { status } = await callHandler({ + const { status, headers } = await callHandler({ url: "/api/error", headers: { Accept: "application/json", }, }); expect(status).toBe(503); + expect(headers).toMatchObject({ + connection: "keep-alive", + "content-type": "application/json", + "content-security-policy": "script-src 'none'; frame-ancestors 'none';", + "referrer-policy": "no-referrer", + "x-content-type-options": "nosniff", + "x-frame-options": "DENY", + }); }); it.skipIf(isWindows && ctx.preset === "nitro-dev")( From a8d8bc97ff3557b391a6da19c2affaadecc326df Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 27 Nov 2024 18:58:37 +0100 Subject: [PATCH 3/3] remove connection header from test --- test/tests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tests.ts b/test/tests.ts index d73aeb0150..122e06c735 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -386,7 +386,6 @@ export function testNitro( }); expect(status).toBe(503); expect(headers).toMatchObject({ - connection: "keep-alive", "content-type": "application/json", "content-security-policy": "script-src 'none'; frame-ancestors 'none';", "referrer-policy": "no-referrer",