Skip to content

Fix cross-request header leakage in proxy - #211

Merged
renan628 merged 2 commits into
masterfrom
fix-proxy-header-isolation
Oct 2, 2026
Merged

renan628 merged 2 commits into
masterfrom
fix-proxy-header-isolation

Conversation

@renan628

@renan628 renan628 commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Problem

The proxy temporarily replaced the shared NextResponse.next method while awaiting application middleware. Overlapping requests could inherit another visitor's headers, including a preview token. Out-of-order completion could also leave a stale wrapper installed after both requests finished.

Solution and guarantees

Replace per-request patching/restoration with a stable interceptor backed by Next's AsyncLocalStorage.

  • Request isolation: every invocation gets its own scope, including nested calls, excluded routes, and requests without a matching handler.
  • Bounded lifetime: the context helper owns activation and cleanup on success and failure, so detached async work cannot keep injecting an ended request's context. Application callbacks are never retried.
  • Idempotent initialization: synchronous installation and a per-constructor symbol registry handle concurrent startup, ESM/CJS imports, compatible duplicate packages, and reloads without stacking wrappers.
  • Conservative fallback: missing or closed context means no automatic injection; explicit headers retain native behavior. Missing required context can still make fetchContent() fail.

This isolates Croct's automatic forwarding while preserving the public API, header precedence, dependencies, and supported runtime ranges. Production changes are limited to the proxy and its internal context helper.

Validation

  • Five deterministic regressions failed before the fix and pass afterward, covering both completion orders and residual contamination.
  • 284 unit tests pass; proxy/context suites also pass in randomized order. Lint, TypeScript validation, and build pass.
  • The simplified implementation was revalidated with real Next 16.1.7 / Node 24.21.0, production Webpack and a local content-service fixture: App/Pages Router, redirects, rewrites, cookies, and errors.
  • 10,000 packaged proxy invocations, at concurrency 1/10/100, with no cross-request contamination and the heap-retention guard passing; ESM/CJS duplicates and context-module reloads also pass.

Randomizing the entire suite exposes a pre-existing console-mock order dependency in fetchContent.test.ts, reproduced independently and left outside this fix.

The integration/load harness was used locally; this PR includes only the fix and focused source regression tests. Deployment-specific staging validation remains a release step.

@renan628 renan628 added the bug Something isn't working label Oct 2, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@croct/plug-next@211

commit: 9a8dc32

@renan628
renan628 merged commit df04f94 into master Oct 2, 2026
7 of 8 checks passed
@renan628
renan628 deleted the fix-proxy-header-isolation branch October 2, 2026 19:02
@renan628 renan628 self-assigned this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants