diff --git a/packages/vinext/src/config/config-matchers.ts b/packages/vinext/src/config/config-matchers.ts index 079a424f..2d7feccc 100644 --- a/packages/vinext/src/config/config-matchers.ts +++ b/packages/vinext/src/config/config-matchers.ts @@ -658,12 +658,6 @@ export async function proxyExternalRequest( headers.set("host", targetUrl.host); // Remove headers that should not be forwarded to external services headers.delete("connection"); - // Strip credentials and internal headers to prevent leaking auth tokens, - // session cookies, and middleware internals to third-party origins. - headers.delete("cookie"); - headers.delete("authorization"); - headers.delete("x-api-key"); - headers.delete("proxy-authorization"); const keysToDelete: string[] = []; for (const key of headers.keys()) { if (key.startsWith("x-middleware-")) { diff --git a/packages/vinext/src/server/app-dev-server.ts b/packages/vinext/src/server/app-dev-server.ts index 4b7bb013..32cbdc12 100644 --- a/packages/vinext/src/server/app-dev-server.ts +++ b/packages/vinext/src/server/app-dev-server.ts @@ -1238,12 +1238,6 @@ async function __proxyExternalRequest(request, externalUrl) { const headers = new Headers(request.headers); headers.set("host", targetUrl.host); headers.delete("connection"); - // Strip credentials and internal headers to prevent leaking auth tokens, - // session cookies, and middleware internals to third-party origins. - headers.delete("cookie"); - headers.delete("authorization"); - headers.delete("x-api-key"); - headers.delete("proxy-authorization"); for (const key of [...headers.keys()]) { if (key.startsWith("x-middleware-")) headers.delete(key); } diff --git a/tests/app-router.test.ts b/tests/app-router.test.ts index 3fca677e..b62b96f3 100644 --- a/tests/app-router.test.ts +++ b/tests/app-router.test.ts @@ -2910,7 +2910,7 @@ describe("App Router external rewrite proxy credential stripping", () => { await new Promise((resolve) => mockServer?.close(() => resolve())); }); - it("strips credential headers from proxied requests to external rewrite targets", async () => { + it("forwards credential headers through proxied requests to external rewrite targets", async () => { mockResponseMode = "plain"; capturedHeaders = null; @@ -2926,11 +2926,11 @@ describe("App Router external rewrite proxy credential stripping", () => { }); expect(capturedHeaders).not.toBeNull(); - // Credential headers must be stripped - expect(capturedHeaders!["cookie"]).toBeUndefined(); - expect(capturedHeaders!["authorization"]).toBeUndefined(); - expect(capturedHeaders!["x-api-key"]).toBeUndefined(); - expect(capturedHeaders!["proxy-authorization"]).toBeUndefined(); + // Credential headers must be forwarded (matching Next.js behavior) + expect(capturedHeaders!["cookie"]).toBe("session=secret123"); + expect(capturedHeaders!["authorization"]).toBe("Bearer tok_secret"); + expect(capturedHeaders!["x-api-key"]).toBe("sk_live_secret"); + expect(capturedHeaders!["proxy-authorization"]).toBe("Basic cHJveHk="); // Internal middleware headers must be stripped expect(capturedHeaders!["x-middleware-next"]).toBeUndefined(); // Non-sensitive headers must be preserved diff --git a/tests/shims.test.ts b/tests/shims.test.ts index eb6368e5..bc417fbd 100644 --- a/tests/shims.test.ts +++ b/tests/shims.test.ts @@ -3813,7 +3813,7 @@ describe("proxyExternalRequest", () => { } }); - it("strips credentials and x-middleware-* headers from proxied requests", async () => { + it("forwards credential headers and strips x-middleware-* headers from proxied requests", async () => { const { proxyExternalRequest } = await import( "../packages/vinext/src/config/config-matchers.js" ); @@ -3842,11 +3842,12 @@ describe("proxyExternalRequest", () => { try { await proxyExternalRequest(request, "https://api.example.com/data"); expect(capturedHeaders).toBeDefined(); - // Sensitive headers must be stripped - expect(capturedHeaders!.get("cookie")).toBeNull(); - expect(capturedHeaders!.get("authorization")).toBeNull(); - expect(capturedHeaders!.get("x-api-key")).toBeNull(); - expect(capturedHeaders!.get("proxy-authorization")).toBeNull(); + // Credential headers must be forwarded (matching Next.js behavior) + expect(capturedHeaders!.get("cookie")).toBe("session=secret123"); + expect(capturedHeaders!.get("authorization")).toBe("Bearer tok_secret"); + expect(capturedHeaders!.get("x-api-key")).toBe("sk_live_secret"); + expect(capturedHeaders!.get("proxy-authorization")).toBe("Basic cHJveHk="); + // Internal middleware headers must be stripped expect(capturedHeaders!.get("x-middleware-rewrite")).toBeNull(); expect(capturedHeaders!.get("x-middleware-next")).toBeNull(); // Non-sensitive headers must be preserved