fix: add Vary header to SSR and RSC responses (#91)
* fix: add Vary: RSC, Accept header to prevent CDN cache poisoning
Add Vary: RSC, Accept to all App Router RSC stream and HTML SSR
responses to prevent CDN cache poisoning. Without this header, a CDN
or reverse proxy may cache an RSC stream response and serve it to a
browser expecting HTML (or vice versa), breaking the page.
Affected response types in app-dev-server.ts:
- Main RSC stream responses (client-side navigation)
- HTML SSR responses (all cache control variants)
- Not-found/forbidden/unauthorized fallback pages (RSC and HTML)
- Error boundary pages (RSC and HTML)
- Server action redirect and re-render responses
- Intercepting route RSC stream responses
Fix Vary header merging in prod-server.ts:
- sendWebResponse: merge Accept-Encoding with existing Vary values
instead of overwriting (preserves RSC, Accept from upstream)
- sendCompressed: same merge behavior for buffered responses
Scope analysis (intentionally NOT changed):
- Pages Router: no RSC/HTML content negotiation on same URL
- Route handler responses: content type is handler-controlled
- Metadata routes: serve single content type per URL
- Static assets: no content negotiation
- Error/redirect responses: not cached or content-negotiated
- Worker entry (app-router-entry.ts): passes through RSC handler
responses which already include the Vary header
Closes GHSA-jgqv-mvrh-hv36
Related: GHSA-r2fc-ccr8-96c4 (Next.js equivalent)
* remove advisory reference from code comment
---------
Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com>