Skip to content

plugin-rsc: cross-origin stylesheet resources omit crossOrigin and can poison browser CORS cache #1464

Description

@jaden-chen

Summary

With plugin-rsc 0.5.34, both generated Resources stylesheet links and SSR ReactDOM.preinit(href, { as: 'style' }) omit crossOrigin. Cross-origin CSS can consequently be cached from a non-CORS request and fail a later CORS fetch of the same URL.

The omission also appears in main at df9f995 (src/plugin.ts generateResourcesCode and src/ssr/shared.ts preloadDeps). I did not find a supported option controlling these attributes; cssLinkPrecedence does not address request mode.

Runnable minimal reproduction

https://gist.github.com/jaden-chen/64f2ea68397a9d5844c28da4abb71a74

Node 26, Vinext 1.0.0-beta.9, plugin-rsc 0.5.34, Vite 8.3.0, React 19.3.0. The fixture builds a tiny real App Router application and serves its generated assets from a second local origin. No service worker or application recovery code is present. It models an asset origin that returns ACAO and Vary: Origin only when an Origin header is sent (observed with R2), with immutable cache headers.

  1. Initial server-imported and client-component stylesheets load through links without crossorigin.
  2. Fetch those same URLs from JavaScript with default CORS mode.
  3. Chromium reuses the non-CORS response and rejects it because ACAO is missing.
  4. A cache-reload CORS fetch succeeds. This is not a missing allowlist or missing asset.

Expected / proposed correction

Consistent anonymous CORS for CSS resource generation, matching Vite's ordinary HTML stylesheet generation and RSC's adjacent module preload behavior:

  • crossOrigin: 'anonymous' in the generated Resources link props.
  • crossOrigin: 'anonymous' in SSR CSS preinit options.

A version-checked local patch to these paths passes initial rendering, navigation and warm-cache checks without a worker. The fixture also uncovered a separate Vinext next/dynamic preload omission, which is being reported there independently.

Happy to adjust the proposed correction if the intended contract is a configurable crossOrigin policy rather than a default. The reproduction intentionally distinguishes origin behavior from framework request consistency.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions