ghsa-xqc2-xf4c-x3h3-header-16x9

GHSA-xqc2-xf4c-x3h3: What the React Server Components Typed-Array RCE Means for Your Next.js Apps

November 08, 2026

GHSA-xqc2-xf4c-x3h3: What the React Server Components Typed-Array RCE Means for Your Next.js Apps

Book a Demo

React fixed a critical, unauthenticated remote code execution flaw in its Server Components packages on 14 October 2026 (GHSA-xqc2-xf4c-x3h3, CVSS v4 9.5). What we found: the trigger is narrow and this is not React2Shell 2.0, but the flaw is easy to miss because it has no CVE, it hides in a copy of React that Next.js ships inside itself, and upgrading react alone does not close it.

TL;DR

React published the advisory on 14 October 2026, with no CVE ID. Next.js published its own advisory for the same bug, GHSA-673q-mjm6-r5xr, and shipped the fix less than an hour after React. We flagged the advisory on X. This post explains what the patch actually changes, which claims hold up, and where teams lose sight of it.

  • The trigger is narrow. React says it needs a response that carries multiple typed arrays plus an attacker-controlled value. In Next.js, that means a use cache function that returns typed arrays.
  • This is not React2Shell 2.0. Based on the patch, the bug is a framing problem in React’s wire protocol, not a deserialization gadget chain. No exploitation in the wild has been reported.
  • “Extremely rare” is not “safe”. Vercel says there is no workaround and to upgrade even if your app has no such functions.
  • Your scanner may not see it. There is no CVE, and Next.js bundles its own copy of the vulnerable packages.
  • Upgrading react does not fix Next.js. Upgrade next itself.

Fixed versions: react-server-dom-webpack, react-server-dom-parcel and react-server-dom-turbopack 19.0.9, 19.1.10, 19.2.9 and 19.3.1. Next.js 16.4.1. The Next.js advisory lists 16.0.0 through 16.4.0 as affected.

What is GHSA-xqc2-xf4c-x3h3?

It is an unauthenticated RCE in the server side of React Server Components (RSC).

RSC lets React run components on the server and stream the result to the browser. Server and client talk through React’s own wire format, called Flight. The three affected packages implement that format for the webpack, Parcel and Turbopack bundlers.

The affected versions are 19.0.0 through 19.0.8, 19.1.0 through 19.1.9, 19.2.0 through 19.2.8 and 19.3.0. React states that apps without a server, or without a framework or bundler that supports RSC, are not affected.

The same release also fixed a separate denial of service in Server Functions, GHSA-h3gv-c5rc-p453.

How does the bug actually work?

The fix points to two places where the Flight protocol could lose track of its own data.

  • Stream fields shared a namespace with regular parts. When the client serialized a stream, it wrote the stream’s chunks under the same form-field keys used for ordinary part IDs. The patch moves streams into their own namespace, so the two can no longer collide.
  • A detached buffer broke the binary framing. Several typed arrays can be views on one underlying ArrayBuffer. If that buffer is detached while the response is being written, the views report a length of zero. The server silently skipped zero-length chunks, while the length headers it had already written still promised the data. The stream and its framing fell out of sync. The patched server now refuses to send a detached buffer and throws an error instead.

In one sentence: the server could announce bytes it never sent, and the reader would then trust the wrong bytes.

React has not published how this desync becomes code execution, and we have not reproduced it. We describe the mechanism the patch fixes, not a working exploit.

Is this React2Shell all over again?

No. It lives in the same three packages as React2Shell (CVE-2025-55182), which attackers exploited at scale in December 2025. The similarities end there.

  • “It’s React2Shell 2.0.” No. React2Shell abused unsafe deserialization of client input and worked against default setups. This bug needs a specific response shape and an attacker-controlled value inside it.
  • “It’s memory corruption.” Misleading. Some coverage describes it that way. The fix is in React’s JavaScript serializer and addresses protocol framing, not a native memory bug.
  • “Extremely rare means I’m safe.” No. Teams often don’t know which cached functions return typed arrays, especially when one is returned indirectly. That is why Vercel tells everyone on an affected version to upgrade.
  • “Only Next.js is affected.” No. Any framework or custom setup built on the three RSC packages is in scope.
  • “It’s being exploited.” No public reports. We have not seen a public proof of concept for this bug. The proof of concept circulating in late October belongs to a different flaw, the Node.js Brotli bug known as Node2Shell.

Why might your tooling have missed it?

Because almost every usual signal was missing.

  • No CVE. Neither the React advisory nor the Next.js advisory has a CVE ID. Tools that key on CVEs see nothing.
  • Late in the feeds. In the first days, the advisories were not in npm’s advisory feed, so npm audit stayed quiet. The Next.js advisory entered the GitHub Advisory Database as a reviewed advisory on 22 October, eight days after the fix.
  • A vendored copy. Next.js compiles its own copy of the RSC runtime into the next package. A dependency check for react-server-dom-webpack in a Next.js app can come back empty while the vulnerable code is there.
  • The wrong upgrade. Bumping react and react-dom leaves the bundled copy untouched. Only a new next release replaces it.

The practical takeaway: for Next.js, track the next version, not the React version.

Who is actually exposed?

  • Next.js 16.0.0 to 16.4.0 with the App Router and Cache Components: patch first. This is the configuration the Next.js advisory names.
  • Next.js 16 apps that don’t use use cache: still upgrade. Vercel offers no workaround and recommends upgrading regardless.
  • Other RSC frameworks and custom setups: affected if they run the three packages at 19.0.0 through 19.3.0. React on Rails, for example, shipped a release that pulls the fixed packages.
  • Client-only React apps: not affected.
  • Preview and branch deployments: they keep running the old bundle until they are redeployed or deleted.

What should security teams do now?

  • Upgrade Next.js 16 to 16.4.1 or later. Run npm ls next in every repository and image to find what is actually resolved.
  • Outside Next.js, upgrade the RSC packages directly to 19.0.9, 19.1.10, 19.2.9 or 19.3.1, and move react and react-dom with them.
  • Redeploy or remove old preview deployments. A fixed lockfile does not change a build that is already running.
  • Don’t rely on npm audit or CVE feeds alone for this one. Check the advisory IDs directly.
  • Don’t grep for typed arrays to decide whether to patch. Upgrading is faster than proving a negative.
  • Watch the runtime while you roll out. A Node.js server process that starts a shell or an unexpected child process deserves an immediate look.

How can Upwind help?

This bug shows how a critical flaw can stay invisible when it has no CVE and sits inside another package. Upwind inventories the packages actually present in your images and running workloads, so you can see which services run an affected next or RSC package and which of them face the internet.

Because there are no public exploitation indicators for this bug, the reliable signal is what happens after a compromise. Upwind watches process execution and lineage at runtime, including a Node.js server that suddenly spawns a shell or an unexpected child process.

To learn more about how Upwind finds vulnerable packages in running workloads and detects post-exploitation activity at runtime, schedule a demo.

Demo the Upwind Platform

See how Upwind is reducing risk and strengthening cloud security for global enterprises.
Get a Demo
Contents
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Threat RSS
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Main RSS