Skip to content
MDView as Markdown

React Router

React Router - and Remix, which it grew out of - renders inline scripts of its own, so a strict policy needs a nonce reaching each of them. The framework handles the propagation for you, with one exception that catches people out when streaming.

What React Router gives you

  • A nonce prop on <Scripts>, <ScrollRestoration> and <LiveReload>, passed straight through to the rendered <script> tags.
  • A nonce prop on <ServerRouter>, which becomes the default for nonce-aware components including <Links>, <Scripts> and <ScrollRestoration>. It is proxied through React context, so you set it once.
  • Per-component overrides: a nonce on an individual component wins over the <ServerRouter> value.

Setting the header

Generate the nonce per request, set it on the header, and pass the same value into <ServerRouter>. Your URL comes from the Setup page:

const nonce = crypto.randomBytes(16).toString('base64')
responseHeaders.set(
  'Content-Security-Policy-Report-Only',
  `default-src 'self'; script-src 'self' 'nonce-${nonce}' 'strict-dynamic'; ` +
  `report-uri https://abc123.report-uri.com/r/d/csp/reportOnly`,
)

Things to watch for

  • Streaming needs the nonce in three places, not one: the Content-Security-Policy header, the nonce-aware components, and the renderToPipeableStream call in entry.server.ts. Miss the third and the shell renders while the streamed chunks get blocked - which looks like a hydration bug rather than a policy problem.
  • <ScrollRestoration> must be rendered immediately before <Scripts>. That is a framework requirement independent of CSP, but getting it wrong while also introducing a nonce makes the cause much harder to see.
  • Setting the nonce on <ServerRouter> covers the framework's components, not third-party scripts in your root route. Those need their own policy entries or their own nonce attributes.

Official documentation

React Router - Security

Start Monitoring with Report URI

Already using us for CSP? Find your report-uri value on Setup, or view your CSP reports.

New to Report URI? Create an account and grab your report-uri value from the Setup page.

Start your free trial