Jun 4, 2026·6 min read·4 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.
An application-level Denial of Service vulnerability exists in the Strawberry GraphQL library (versions 0.71.0 through 0.315.6) due to uncontrolled recursion within the QueryDepthLimiter and MaxAliasesLimiter extensions when processing circular fragment references.
A security flaw in strawberry-graphql versions 0.172.0 through 0.315.6 allows unauthenticated attackers to bypass the MaxAliasesLimiter extension. By utilizing GraphQL fragment spreads, clients can trigger high levels of alias amplification, causing uncontrolled backend resource consumption and application-level Denial of Service.
CVE-2026-48710 is a critical security-desynchronization vulnerability in the Starlette ASGI framework (versions >= 0.8.3, < 1.0.1) that allows remote attackers to bypass path-based security middleware and access-control decorators. By injecting URI authority-to-path delimiters into the Host header, attackers can manipulate the application-level parsed URL path while the underlying ASGI server dispatches the request to target endpoints.
CVE-2026-20230 is a critical Server-Side Request Forgery (SSRF) vulnerability in the WebDialer service of Cisco Unified Communications Manager (Unified CM) and Cisco Unified Communications Manager Session Management Edition (Unified CM SME). The flaw arises from improper validation of input parameters within WebDialer HTTP requests. Unauthenticated remote attackers can exploit this vulnerability to force the application to make HTTP requests to internal administrative services bound to the loopback interface. In the Cisco Voice Operating System (VOS) environment, these local services trust loopback traffic inherently, permitting unauthorized file writes. By writing malicious files to specific system directories, the attacker can execute arbitrary commands with root privileges.
CVE-2026-48526 is an algorithm-confusion vulnerability in PyJWT prior to version 2.13.0. When an application decodes tokens using a raw JSON Web Key (JWK) string while simultaneously supporting mixed algorithm families (symmetric and asymmetric), PyJWT does not validate that the key matches its intended algorithm context. This allows an attacker to sign a forged token using the public JWK string as an HMAC symmetric secret, bypassing authentication controls.
CVE-2026-23479 is a critical Use-After-Free (UAF) vulnerability inside the blocking-client code path of the Redis in-memory data structure server. In affected versions from 7.2.0 until 8.6.3, the unblock client flow fails to handle an error return from processCommandAndResetClient when re-executing a previously blocked command. If a blocked client is evicted due to maxmemory limits or client eviction policies during this command processing flow, its client structure is freed. Because the caller ignores the error return and continues processing, it attempts to read and write properties on the freed client structure, leading to a Use-After-Free condition.