diff --git a/.changeset/brown-apes-kick.md b/.changeset/brown-apes-kick.md new file mode 100644 index 000000000..e02b5be54 --- /dev/null +++ b/.changeset/brown-apes-kick.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/aws": patch +--- + +fix: Validate statusCode is number and not NaN in OpenNextNodeResponse constructor diff --git a/examples/app-router/middleware.ts b/examples/app-router/middleware.ts index a634eb4a2..e5da8f98c 100644 --- a/examples/app-router/middleware.ts +++ b/examples/app-router/middleware.ts @@ -28,6 +28,12 @@ export function middleware(request: NextRequest) { const u = new URL("https://opennext.js.org/share.png"); return NextResponse.rewrite(u); } + if (path === "/rewrite-status-code") { + const u = new URL("/rewrite-destination", `${protocol}://${host}`); + return NextResponse.rewrite(u, { + status: 403, + }); + } if (path === "/cookies") { const res = NextResponse.next(); res.cookies.set("foo", "bar"); diff --git a/packages/open-next/src/http/openNextResponse.ts b/packages/open-next/src/http/openNextResponse.ts index 1aca850a5..dac069034 100644 --- a/packages/open-next/src/http/openNextResponse.ts +++ b/packages/open-next/src/http/openNextResponse.ts @@ -74,7 +74,14 @@ export class OpenNextNodeResponse extends Transform implements ServerResponse { statusCode?: number, ) { super(); - if (statusCode !== undefined) { + // We only set the status code if it is not a NaN and it is a number + // Only allow status codes between 100 and 599 https://httpwg.org/specs/rfc9110.html#status.codes + if ( + statusCode && + Number.isInteger(statusCode) && + statusCode >= 100 && + statusCode <= 599 + ) { this.statusCode = statusCode; } } diff --git a/packages/tests-e2e/tests/appRouter/middleware.rewrite.test.ts b/packages/tests-e2e/tests/appRouter/middleware.rewrite.test.ts index a89d85832..7a56ac49b 100644 --- a/packages/tests-e2e/tests/appRouter/middleware.rewrite.test.ts +++ b/packages/tests-e2e/tests/appRouter/middleware.rewrite.test.ts @@ -32,3 +32,12 @@ test("Middleware Rewrite External Image", async ({ page }) => { expect(validateMd5(bodyBuffer, OPENNEXT_PNG_MD5)).toBe(true); }); }); + +test("Middleware Rewrite Status Code", async ({ page }) => { + await page.goto("/rewrite-status-code"); + const el = page.getByText("Rewritten Destination", { exact: true }); + await expect(el).toBeVisible(); + page.on("response", async (response) => { + expect(response.status()).toBe(403); + }); +});