[GH-ISSUE #988] Validate RSC request headers to prevent CDN cache poisoning #216

Closed
opened 2026-05-06 12:38:15 +02:00 by BreizhHardware · 0 comments

Originally created by @github-actions[bot] on GitHub (Apr 30, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/988

Upstream change

Next.js enabled experimental.validateRSCRequestHeaders by default in vercel/next.js#93367 (commit 4ba05cc).

This flag has been enabled by default on canary for some time. This turns it on by default to ensure that CDNs that don't respect Vary properly distinguish between different response types.

Why this matters for vinext

App Router responses come in three flavors that share the same URL but differ by request headers:

  • HTML document (no RSC header)
  • RSC payload (RSC: 1)
  • Prefetch RSC payload (RSC: 1, Next-Router-Prefetch: 1)

A CDN that does not honor Vary: RSC, Next-Router-Prefetch, ... can cache one variant and serve it for a request that asked for a different variant. For Cloudflare deployments behind a CDN (Cloudflare cache, Workers' built-in cache, or any upstream CDN) this is a real cache-poisoning risk.

validateRSCRequestHeaders is Next.js's defense-in-depth: when a request arrives with the RSC header but other expected RSC headers are missing or inconsistent (a fingerprint of cache-poisoned content), the server treats the request as a regular HTML navigation instead of trusting the cached RSC response.

Action

  • Audit how vinext's App Router server (server/app-*.ts, entries/app-rsc-entry.ts) distinguishes HTML / RSC / prefetch-RSC requests
  • Confirm Vary headers are set correctly on every App Router response so well-behaved CDNs distinguish the variants
  • Port Next.js's validateRSCRequestHeaders validation: when an incoming RSC-shaped request fails the integrity check, fall back to the HTML render path
  • Search the Next.js source/tests for the exact validation logic and headers checked (.nextjs-ref/packages/next/src/, search for validateRSCRequestHeaders)
  • Add a test that mimics a CDN serving the wrong variant and asserts vinext recovers safely

References

Originally created by @github-actions[bot] on GitHub (Apr 30, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/988 ## Upstream change Next.js enabled `experimental.validateRSCRequestHeaders` by default in [vercel/next.js#93367](https://github.com/vercel/next.js/pull/93367) (commit [4ba05cc](https://github.com/vercel/next.js/commit/4ba05cc300cd3f196bdcebe56de2f6811171bb68)). > This flag has been enabled by default on canary for some time. This turns it on by default to ensure that CDNs that don't respect `Vary` properly distinguish between different response types. ## Why this matters for vinext App Router responses come in three flavors that share the same URL but differ by request headers: - HTML document (no `RSC` header) - RSC payload (`RSC: 1`) - Prefetch RSC payload (`RSC: 1`, `Next-Router-Prefetch: 1`) A CDN that does not honor `Vary: RSC, Next-Router-Prefetch, ...` can cache one variant and serve it for a request that asked for a different variant. For Cloudflare deployments behind a CDN (Cloudflare cache, Workers' built-in cache, or any upstream CDN) this is a real cache-poisoning risk. `validateRSCRequestHeaders` is Next.js's defense-in-depth: when a request arrives with the `RSC` header but other expected RSC headers are missing or inconsistent (a fingerprint of cache-poisoned content), the server treats the request as a regular HTML navigation instead of trusting the cached RSC response. ## Action - Audit how vinext's App Router server (`server/app-*.ts`, `entries/app-rsc-entry.ts`) distinguishes HTML / RSC / prefetch-RSC requests - Confirm `Vary` headers are set correctly on every App Router response so well-behaved CDNs distinguish the variants - Port Next.js's `validateRSCRequestHeaders` validation: when an incoming RSC-shaped request fails the integrity check, fall back to the HTML render path - Search the Next.js source/tests for the exact validation logic and headers checked (`.nextjs-ref/packages/next/src/`, search for `validateRSCRequestHeaders`) - Add a test that mimics a CDN serving the wrong variant and asserts vinext recovers safely ## References - Upstream PR: https://github.com/vercel/next.js/pull/93367 - Upstream commit: https://github.com/vercel/next.js/commit/4ba05cc300cd3f196bdcebe56de2f6811171bb68
BreizhHardware 2026-05-06 12:38:15 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#216
No description provided.