The vulnerability is a Cross-Site Scripting (XSS) issue in React Router's <ScrollRestoration> component when Server-Side Rendering (SSR) is enabled. The core of the issue lies in the improper sanitization of user-provided keys (getKey/storageKey) which are used to generate JavaScript code that is then embedded in the server-rendered HTML.
The analysis of the patch commit c89c32c562a7723c45ee71dab1c892acaf7a608d pinpoints the vulnerable code sections.
-
In packages/react-router/lib/dom/lib.tsx, the ScrollRestoration component was found to be directly embedding the storageKey and ssrKey into a <script> tag via dangerouslySetInnerHTML without adequate escaping. This allows an attacker to craft a malicious key containing arbitrary JavaScript, leading to its execution on the rendered page. The fix involves wrapping the keys with an escapeHtml function before they are embedded.
-
In packages/react-router/lib/dom/server.tsx, the StaticRouterProvider component, which is integral to the SSR process, was identified to be using a custom and flawed htmlEscape function for sanitizing hydration data. This function was removed and substituted with the more robust escapeHtml function, the same one used to secure the ScrollRestoration component. This change indicates that the prior escaping mechanism was insufficient and a contributing factor to the vulnerability.
Consequently, during the exploitation of this vulnerability, a runtime profile would likely feature calls to ScrollRestoration, as it is the component that handles the malicious input and generates the vulnerable script. The StaticRouterProvider would also appear in the call stack, as it orchestrates the server-side rendering process where the vulnerability manifests.