Jun 4, 2026·6 min read·156 visits
A dynamic object instantiation flaw in turbo-stream allows unauthenticated remote attackers to crash React Router or Remix applications via crafted payloads that instantiate non-constructor objects or cause out-of-memory errors.
React Router and the underlying turbo-stream vendor library contain a vulnerability allowing remote unauthenticated attackers to trigger a Denial of Service (DoS) or potentially client-side Cross-Site Scripting (XSS) due to unsafe dynamic deserialization of streaming error payloads.
React Router v7 in Framework Mode and Remix v2.9.0+ with Single Fetch enabled contain a vulnerability in the serialization and deserialization library, turbo-stream. This security flaw allows unauthenticated remote attackers to trigger a Denial of Service (DoS) or potentially execute client-side Cross-Site Scripting (XSS) in specific React Server Components (RSC) configurations. The vulnerability is tracked as CVE-2026-34077 and GHSA-rxv8-25v2-qmq8.
The vulnerability stems from the way the underlying turbo-stream vendor library processes stream error data. When rendering streaming responses, the application packages errors and sends them to the client for hydration. A discrepancy exists between official NVD listings, which emphasize client-side XSS via RSC redirects, and the actual code fix, which remedies a server-side and client-side Denial of Service vulnerability during deserialization.
This analysis details the technical mechanics of the deserialization failure, demonstrating how malicious input can lead to resource exhaustion or Node.js process termination. Organizations utilizing React Router's single-fetch features or unstable RSC APIs must assess their vulnerability status and apply the available patches.
The technical flaw resides in the custom serialization algorithm implemented in the turbo-stream component bundled inside the react-router monorepo. Specifically, the vulnerability is located in the files flatten.ts (the serializer) and unflatten.ts (the deserializer). The engine uses these files to transform complex JavaScript objects, such as Error instances, into a flat string representation for over-the-wire streaming.
During serialization, when the engine encounters an object extending the standard Error class, it writes the error message and the constructor name to the stream. If the constructor name is anything other than the default Error, the serializer appends the custom name property to the serialized structure. This name parameter is retrieved directly from the JavaScript object's properties without verification.
During deserialization on the receiving side, the engine attempts to hydrate this serialized payload back into live JavaScript objects. The parsing logic extracts the serialized error name and attempts to resolve it as a constructor on the global execution context. By dynamically instantiating an arbitrary property on the global object, the deserializer introduces an unrestricted object instantiation vector.
An examination of the vulnerable source code compared to the patched version reveals the exact mechanics of the resolution. In the vulnerable version of the deserializer (unflatten.ts), the code parsed the incoming array stream and checked for the third element, which denoted the custom errorType.
// Vulnerable unflatten.ts implementation
case TYPE_ERROR:
const [, message, errorType] = value;
let error =
errorType && globalObj && globalObj[errorType]
? new globalObj[errorType](message)
: new Error(message);
hydrated[index] = error;
set(error);
continue;This dynamic lookup is vulnerable because the global execution context, denoted by globalObj (equivalent to globalThis or window), contains properties that are not callable constructors. When an attacker passes a property name that exists on the global object but cannot be instantiated via the new operator, the JavaScript engine throws a fatal exception.
The fix, introduced in commit 59811921d3c7d599077b8cadccdcd65a233165e0, completely refactors this deserialization branch. The patched version removes the dynamic constructor resolution and instantiates a standard Error object regardless of the supplied name.
// Patched unflatten.ts implementation
case TYPE_ERROR:
const [, message] = value;
let error = new Error(message);
hydrated[index] = error;
set(error);
continue;This modification represents a complete and robust remediation. By eliminating dynamic object instantiation from the stream parsing logic, the attack surface is neutralized, and variant payloads targeting other global constructors are rendered ineffective.
Exploitation of CVE-2026-34077 does not require authentication and can be executed via a crafted HTTP request targeting the Single Fetch or RSC endpoints. An attacker must construct a stream payload containing a serialized error with a malicious errorType parameter. When the application or client attempts to parse this stream, the execution flow is diverted.
To cause an immediate process crash, the attacker targets non-constructor properties on the global execution scope. For example, submitting JSON as the errorType forces the execution of new globalThis.JSON(message). Because JSON is a static namespace and not a constructor, the Node.js runtime throws a fatal TypeError which, if unhandled in the streaming controller, terminates the server process.
Alternatively, the attacker can exploit this behavior to trigger an Out-of-Memory (OOM) condition on the server or the client browser. By supplying a constructor that allocates memory, such as ArrayBuffer, and a very large integer string as the message, the parser executes new ArrayBuffer(2000000000). This instruction causes an immediate and large heap allocation, exhausting available system memory and triggering a garbage collector crash or process termination.
The concrete impact of CVE-2026-34077 primarily manifests as a high-severity Denial of Service (DoS) vulnerability. Exploiting this flaw allows unauthenticated remote attackers to repeatedly crash target Node.js processes, disrupting service availability for all users. In containerized environments, rapid container crashes can lead to orchestration failures and persistent outages.
While the primary risk is Denial of Service, the official NVD record highlights a secondary risk involving client-side Cross-Site Scripting (XSS). In configurations utilizing unstable React Server Components (RSC) APIs, an attacker who controls the destination of an RSC redirect can inject arbitrary client-side code. This risk is constrained to environments exposing RSC routing channels to untrusted input.
The vulnerability carries a CVSS v3.1 base score of 7.5, reflecting a High severity rating. The attack vector is Network, the complexity is Low, and no privileges or user interactions are required to trigger the failure. This low barrier to exploitation increases the likelihood of opportunistic scans and automated exploitation campaigns.
The primary and recommended mitigation for CVE-2026-34077 is upgrading the react-router and turbo-stream packages to the patched releases. For applications utilizing React Router v7, administrators should upgrade to version 7.14.0 or later. For applications using React Router v7 with specific RSC structures, version 7.13.2 contains targeted hotfixes for the redirect-handling vector.
Developers must also ensure that nested dependencies are updated within lockfiles. Run npm update react-router or the equivalent command for your package manager, then verify that turbo-stream is resolved to version 3.0.0 or higher. The presence of the vulnerable library version in dependency trees poses a continued risk even if the root application package appears upgraded.
If immediate patching is not feasible, organizations should employ temporary workarounds to restrict exposure. Implementing rate limiting on single-fetch and RSC streaming routes can reduce the impact of Denial of Service attempts. Additionally, configuring Web Application Firewall (WAF) rules to detect and drop streaming payloads containing anomalous error type sequences can block known exploit vectors at the perimeter.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
react-router remix-run | >= 7.0.0, < 7.14.0 | 7.14.0 |
react-router (RSC context) remix-run | >= 7.7.0, < 7.13.2 | 7.13.2 |
turbo-stream jacob-ebey | < 3.0.0 | 3.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-770 |
| Attack Vector | Network |
| CVSS Score | 7.5 |
| EPSS Score | 0.0004 (12.33 percentile) |
| Impact | Denial of Service (DoS) / Process Crash |
| Exploit Status | Proof-of-Concept / Theoretical |
| CISA KEV Status | Not Listed |
The product allocates resources without limits, making it vulnerable to exhaustion attacks, specifically through dynamic constructor execution during streaming error deserialization.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.
An elevation of privilege vulnerability exists in ASP.NET Core and Microsoft Visual Studio due to improper synchronization during concurrent thread execution. Authenticated remote attackers with low privileges can exploit a timing window to manipulate shared resources and assume higher-level execution contexts.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.