Skip to content

fix: stop stripping credential headers from rewrite proxy requests#277

Merged
southpolesteve merged 2 commits intocloudflare:mainfrom
17hz:fix/preserve-credentials-proxy
Mar 7, 2026
Merged

fix: stop stripping credential headers from rewrite proxy requests#277
southpolesteve merged 2 commits intocloudflare:mainfrom
17hz:fix/preserve-credentials-proxy

Conversation

@17hz
Copy link
Contributor

@17hz 17hz commented Mar 6, 2026

Fixes #264

Problem

proxyExternalRequest and __proxyExternalRequest unconditionally strip cookie, authorization, x-api-key, and proxy-authorization headers from all proxied rewrite requests. This breaks authentication for the most common use case — proxying to the user's own backend.

Context

Next.js does not strip these headers for rewrites. It forwards all request headers as-is to the rewrite destination. vinext's blanket stripping is a deviation from Next.js behavior that breaks real-world usage.

Fix

Remove the credential-stripping logic from both:

  • config-matchers.tsproxyExternalRequest (used by prod server)
  • app-dev-server.ts__proxyExternalRequest (inlined in dev server virtual module)

Internal x-middleware-* headers are still stripped as before.

@james-elicx
Copy link
Collaborator

/bigbonk review

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 6, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@277

commit: 761655b

@james-elicx
Copy link
Collaborator

cc @threepointone - i believe this was related to the security advisory changes

ask-bonk[bot]
ask-bonk bot previously requested changes Mar 6, 2026
Copy link
Contributor

@ask-bonk ask-bonk bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

The behavioral change here is correct — Next.js does not strip credential headers from rewrite proxy requests, and vinext should match that behavior. However, this PR has two problems that need to be addressed before merging.

1. CI is failing: existing tests assert the old behavior

Vitest is failing on both tests/shims.test.ts (line 3707) and tests/app-router.test.ts (line 2748). Both tests explicitly assert that cookie, authorization, x-api-key, and proxy-authorization are stripped from proxy requests — which is exactly the behavior this PR removes.

These tests need to be updated to assert the new behavior: that credential headers are forwarded through the proxy. Specifically:

  • tests/shims.test.ts:3707 — "strips credentials and x-middleware-* headers from proxied requests" should be renamed and updated to verify that cookie, authorization, x-api-key are preserved, while x-middleware-* headers are still stripped.
  • tests/app-router.test.ts:2748 — "strips credential headers from proxied requests to external rewrite targets" — same treatment.

2. Missing parity check: Pages Router prod server

Per AGENTS.md, bug fixes must check dev/prod server parity. The prod server (server/prod-server.ts) and the Cloudflare worker entry (generated by deploy.ts) both delegate to proxyExternalRequest from config-matchers.ts, so they get the fix automatically. The Pages Router dev server (server/dev-server.ts) has no proxy logic, so it's not affected. This is fine — just confirming the parity check was done.

Aside: proxy-authorization as a hop-by-hop header

Note that proxy-authorization is listed in HOP_BY_HOP_HEADERS (config-matchers.ts:15), which is used to strip hop-by-hop headers from upstream responses. This is correct per RFC 2616 — proxy-authorization is a hop-by-hop header that should not be forwarded in responses. But this is orthogonal to the request-side forwarding that this PR addresses. Just flagging for clarity: the request-side proxy-authorization will now be forwarded (matching Next.js), while the response-side is still correctly stripped.

@@ -606,12 +606,6 @@ export async function proxyExternalRequest(
headers.set("host", targetUrl.host);
// Remove headers that should not be forwarded to external services
headers.delete("connection");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The credential-stripping removal here is correct — Next.js forwards all request headers (including cookie, authorization, etc.) to rewrite destinations via http-proxy with no filtering.

However, the existing test at tests/shims.test.ts:3707 ("strips credentials and x-middleware-* headers from proxied requests") asserts the old behavior and is now failing in CI. Please update it to verify that credential headers are preserved while x-middleware-* headers remain stripped.

@@ -1185,12 +1185,6 @@ async function __proxyExternalRequest(request, externalUrl) {
const headers = new Headers(request.headers);
headers.set("host", targetUrl.host);
headers.delete("connection");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above — correct change, but the integration test at tests/app-router.test.ts:2748 ("strips credential headers from proxied requests to external rewrite targets") is now failing. It needs to be updated to match the new forwarding behavior.

@ask-bonk
Copy link
Contributor

ask-bonk bot commented Mar 6, 2026

Review submitted. Here's a summary of what I found:

The behavioral change is correct — I verified that Next.js does not strip credential headers from rewrite proxy requests. It uses http-proxy with changeOrigin: true and forwards all headers as-is. vinext's blanket stripping was a deviation from Next.js behavior.

However, I requested changes because:

  1. CI is failing — Two existing tests (tests/shims.test.ts:3707 and tests/app-router.test.ts:2748) explicitly assert that credential headers are stripped. These tests now fail with expected 'session=secret123' to be null/undefined. The PR needs to update these tests to assert the new forwarding behavior.

  2. Dev/prod parity is fine — The prod server and Cloudflare worker entry both delegate to the shared proxyExternalRequest from config-matchers.ts, so they inherit the fix automatically. The Pages Router dev server has no proxy logic.

github run

@southpolesteve southpolesteve enabled auto-merge (squash) March 7, 2026 02:53
17hz added 2 commits March 7, 2026 16:42
Rewrite destinations are typically the user's own backend services,
not untrusted third-party origins. Stripping cookie, authorization,
x-api-key, and proxy-authorization headers breaks authentication
for proxied API requests.

Next.js does not strip these headers for rewrites either — it
forwards them as-is to the destination.
Update tests to match new behavior where credential headers (cookie,
authorization, x-api-key, proxy-authorization) are forwarded through
the rewrite proxy, matching Next.js behavior. x-middleware-* headers
are still stripped.
@southpolesteve southpolesteve force-pushed the fix/preserve-credentials-proxy branch from 760c0f4 to ae52c07 Compare March 7, 2026 22:44
@southpolesteve southpolesteve dismissed ask-bonk[bot]’s stale review March 7, 2026 22:44

All feedback addressed: tests updated to assert forwarding behavior, parity confirmed, conflicts resolved after rebase onto main.

@southpolesteve southpolesteve disabled auto-merge March 7, 2026 23:28
@southpolesteve southpolesteve enabled auto-merge (squash) March 7, 2026 23:28
@southpolesteve southpolesteve merged commit d471a52 into cloudflare:main Mar 7, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Rewrite proxy strips cookie/authorization headers, breaking backend auth

3 participants