React Server Components RCE GHSA-xqc2-xf4c-x3h3: Patching – ThreatDefence
Skip to content
Security advisories/React (Meta, React Foundation); Vercel (Next.js)
CriticalActive

React Server Components RCE: Patching and Threat Hunting

Anton Guzhevskiy
Anton Guzhevskiy · Principal Product Researcher
Published November 9, 2026

React advisory GHSA-xqc2-xf4c-x3h3, fixed on October 14, 2026, is an unauthenticated remote code execution flaw in React Server Components. Next.js fixed it alongside a critical image-processing RCE, and code claiming to exploit it is public.

TL;DR

Upgrade Next.js to 16.4.5 or 15.5.29 and React server packages to their fixed releases.

At a glance
SeverityCritical
StatusActive
ExploitedNo exploitation reported by React, Vercel or CISA. Public repositories claiming proof-of-concept code appeared on October 17 and November 8, 2026 (not verified by us). No CVE assigned yet, so not in CISA KEV. The earlier React2Shell flaw (CVE-2025-55182) is in CISA KEV with known ransomware use
ProductReact Server Components (react-server-dom-webpack, react-server-dom-parcel and react-server-dom-turbopack 19.0.0 to 19.3.0), Next.js 16.0.0 to 16.4.0 with Cache Components, and Next.js image optimization from 10.0.0 to 15.5.27 and 16.0.0 to 16.4.0
CVEsGHSA-xqc2-xf4c-x3h3 (React, no CVE yet), GHSA-673q-mjm6-r5xr (Next.js), CVE-2026-96889 (image optimization). Related: CVE-2025-55182 (React2Shell)
Fixed inReact 19.0.9, 19.1.10, 19.2.9 and 19.3.1 for react-server-dom-webpack, -parcel and -turbopack. Next.js 16.4.1 and 15.5.28, or 16.4.5 and 15.5.29 with the November fixes. sharp 0.35.5 for the image flaw

React published security advisory GHSA-xqc2-xf4c-x3h3 on October 14, 2026: crafted requests to frameworks that support React Server Components can lead to unauthenticated remote code execution on the server. It is rated critical, CVSS 4.0 9.5, and affects react-server-dom-webpack, react-server-dom-parcel and react-server-dom-turbopack from 19.0.0 to 19.3.0. Fixed versions are 19.0.9, 19.1.10, 19.2.9 and 19.3.1. No CVE ID has been assigned, so the GitHub advisory ID is the identifier to track.

Next.js released 16.4.1 and 15.5.28 the same day. The update fixes the Next.js side of the React flaw (GHSA-673q-mjm6-r5xr, Next.js 16 with Cache Components) and a second critical remote code execution in the Image Optimization API (CVE-2026-96889), caused by a memory flaw in the librsvg library that sharp uses to decode SVG on glibc-based Linux.

This is the second unauthenticated remote code execution flaw in React Server Components in under a year. The first, React2Shell (CVE-2025-55182), was exploited within hours of its disclosure in December 2025 and is listed by CISA as used in ransomware campaigns. Any application still running a December 2025 version is exposed to both.

What was fixed on October 14

Advisory Component Severity Affected Fixed
GHSA-xqc2-xf4c-x3h3 React Server Components: unauthenticated remote code execution Critical, CVSS 4.0 9.5 react-server-dom-* 19.0.0 to 19.3.0 19.0.9, 19.1.10, 19.2.9, 19.3.1
GHSA-673q-mjm6-r5xr Next.js use cache functions returning typed arrays: unauthenticated remote code execution Critical Next.js 16.0.0 to 16.4.0 16.4.1
CVE-2026-96889 / GHSA-2464-fhr4-w9xw Next.js Image Optimization with SVG on glibc Linux (librsvg in sharp): remote code execution Critical (Next.js); CVSS 3.1 7.8 for librsvg Next.js 10.0.0 to 15.5.27 and 16.0.0 to 16.4.0 15.5.28, 16.4.1; sharp 0.35.5
GHSA-h3gv-c5rc-p453 / GHSA-p3m5-59mp-jv5r React Server Functions and Next.js Server Actions: denial of service High, CVSS 4.0 8.2 Same React versions; Next.js App Router with a Server Action Same releases

Next.js followed with its scheduled November 3, 2026 release, 16.4.5 and 15.5.29, which fixes seven cache-disclosure and header issues of high and medium severity. Upgrade to those versions rather than stopping at the October releases.

How the flaw works

React and Vercel have published little technical detail, to give users time to patch. What they have said:

  • React Server Components send data between server and client in React’s own serialization format, often called the Flight protocol. The flaw is in how that format handles typed arrays (such as Uint8Array) when a response carries several of them together with a value the attacker controls.
  • React describes this as affecting “extremely rare cases”. Next.js narrows it to App Router applications with Cache Components enabled and a use cache function that returns multiple typed arrays.
  • Both projects still say to upgrade immediately, and Next.js adds that you should upgrade “even if your application does not have similar functions”. There is no known workaround.
  • No login is needed, and the attack arrives as ordinary HTTP requests to the application.

The image flaw is separate. The Next.js Image Optimization API passes images to sharp, which uses libvips and librsvg to decode SVG. CVE-2026-96889 is a use-after-free in librsvg when an SVG contains nested XML inclusions with duplicate entity declarations. Next.js rates it critical because an attacker can supply the SVG through the image endpoint.

Who is exposed, in priority order

  1. Any application still on a React2Shell-vulnerable version: React Server Components packages before 19.0.1, 19.1.2 or 19.2.1, or Next.js 15.x and 16.x before the December 2025 patches. These have been exploited at scale since December 2025. Treat any that faced the internet as possibly compromised.
  2. Internet-facing Next.js 16.0.0 to 16.4.0 applications that use Cache Components (cacheComponents in next.config) and use cache, especially self-hosted ones on next start, in containers or on VMs.
  3. Every other Next.js 16 application below 16.4.1. Next.js advises upgrading even without such functions.
  4. Next.js applications on glibc-based Linux that use image optimization (next/image or /_next/image) with a sharp version below 0.35.5. This covers Next.js 10.0.0 to 15.5.27, so older 15.x lines need to move to 15.5.28 or later. Alpine-based (musl) images are outside the scope Next.js describes for this flaw.
  5. Other frameworks and bundlers that support React Server Components: React Router’s RSC mode, Waku, @parcel/rsc, @vitejs/plugin-rsc and RedwoodSDK (rwsdk). These pull in the react-server-dom-* packages directly.

Outside the scope of the React flaw: applications whose React code runs only in the browser, applications that do not use a framework or bundler supporting React Server Components, and Next.js sites exported as static files (output: 'export'), which run no React server. Next.js 15 is outside the scope of GHSA-673q-mjm6-r5xr but still needs 15.5.28 or later for the image flaw.

Affected and fixed versions

React Server Components packages (react-server-dom-webpack, react-server-dom-parcel, react-server-dom-turbopack):

Release line Affected Fixed
19.0 19.0.0 to 19.0.8 19.0.9
19.1 19.1.0 to 19.1.9 19.1.10
19.2 19.2.0 to 19.2.8 19.2.9
19.3 19.3.0 19.3.1

Next.js:

Release line Support Fixed for October 14 issues Latest, with November 3 fixes
16.4 Active LTS 16.4.1 16.4.5
15.5 Maintenance LTS 15.5.28 15.5.29
16.0 to 16.3, 15.0 to 15.4, 14.x and older No fixes released Move to 16.4.5 or 15.5.29

Next.js bundles its own copy of the React server packages, so for Next.js applications the next version is what matters. Upgrading react and react-dom alone does not fix it.

CVE CVSS EPSS CISA KEV Fixed in
CVE-2026-96889 7.8 High (v3.1, librsvg) 0.6% No Next.js 15.5.28 or 16.4.1, or sharp 0.35.5
CVE-2025-55182 10.0 Critical (v3.1) 99.7% Yes, added December 5, 2025 React 19.0.1, 19.1.2 or 19.2.1, and the December 2025 Next.js releases

CVSS and EPSS from NVD and FIRST, exploitation status from the CISA Known Exploited Vulnerabilities catalog, checked November 9, 2026.

How to check your applications

Run these in each application’s source folder or build output. They only read files:

# Next.js version and the bundled React server packages
node -p "require('next/package.json').version"
npm ls next react react-server-dom-webpack react-server-dom-turbopack react-server-dom-parcel sharp --all 2>/dev/null

# Is Cache Components on, and are there use cache functions?
grep -nE "cacheComponents" next.config.* 2>/dev/null
grep -rlE "[\"']use cache[\"']" app src 2>/dev/null | head

# Static export? (no React server at runtime)
grep -nE "output:\s*['\"]export['\"]" next.config.* 2>/dev/null

On servers and in containers, find every installed copy, including ones in old releases left on disk:

find / -path '*/node_modules/next/package.json' -not -path '/proc/*' 2>/dev/null -exec grep -H '"version"' {} \;
find / -path '*/node_modules/react-server-dom-*/package.json' -not -path '/proc/*' 2>/dev/null -exec grep -H '"version"' {} \;
find / -path '*/node_modules/sharp/package.json' -not -path '/proc/*' 2>/dev/null -exec grep -H '"version"' {} \;

For container images, run the same node -p command inside a running container, or scan the image with a scanner that reads the GitHub Advisory Database, since the React flaw has a GHSA ID but no CVE yet. In GitHub, Dependabot alerts list GHSA-xqc2-xf4c-x3h3 and GHSA-673q-mjm6-r5xr against package-lock.json, yarn.lock and pnpm-lock.yaml.

An application is exposed to the React flaw if any react-server-dom-* copy is below the fixed version for its line, or next is 16.0.0 to 16.4.0. It is exposed to the image flaw if next is below 15.5.28 (or 16.0.0 to 16.4.0) and the installed sharp is below 0.35.5 on glibc Linux.

Mitigation and remediation

  1. Upgrade Next.js to 16.4.5 or 15.5.29, then rebuild and redeploy. Lock files must change; a redeploy of the old build does not pick up the fix.
npm install next@16.4.5    # 16.x
npm install next@15.5.29   # 15.x
  1. For other React Server Components frameworks, upgrade the server package to the fixed release for your line and update the framework:
npm install react@latest react-dom@latest react-server-dom-webpack@latest   # or -parcel / -turbopack
  1. If you cannot upgrade Next.js today, close the image flaw by forcing sharp 0.35.5 or later through overrides (npm), resolutions (Yarn) or pnpm.overrides, then rebuild. There is no workaround for the React flaw; plan the upgrade within days, not weeks.
  2. Rebuild container images from scratch and redeploy. Running containers keep the old code.
  3. Remove old builds and unused deployments that still run vulnerable versions, such as preview environments, staging servers and forgotten demo apps.
  4. Use web application firewall rules only as a stopgap. Cloud and CDN providers added rules for React2Shell, but React and Vercel both say not to rely on them.
  5. Rotate secrets that the application could read (environment variables, API keys, database and cloud credentials) if it was internet-facing on a vulnerable version and any of the hunts below return results. Vercel gave this advice for React2Shell to anyone unpatched after December 4, 2025.

Threat hunting

Exploitation of these flaws runs attacker code inside the Node.js process that serves the application. Requests look like ordinary POST requests to application routes, and the server-side signal is what Node.js does next: start a shell, download and run a file, read secrets or connect out. That is how React2Shell exploitation was seen in December 2025: system and environment reconnaissance, reverse shells, cryptominers, backdoors, and theft of cloud and Kubernetes credentials, according to Microsoft.

Microsoft Defender and Sentinel queries

The KQL below is example code for Microsoft Defender XDR advanced hunting and Microsoft Sentinel. Adapt table and field names to your environment and test each query before relying on it. Build servers and developer machines run Node.js tooling legitimately; scope the queries to production web servers and containers, or add exclusions.

Hunt 1: shells and reconnaissance started by the Node.js server

// Example: Defender for Endpoint, shells and recon commands started by Node.js
let ShellOrRecon = dynamic(["sh", "bash", "dash", "ash", "zsh", "cmd.exe", "powershell.exe", "pwsh", "pwsh.exe",
    "whoami", "whoami.exe", "id", "uname", "hostname", "curl", "wget", "nc", "ncat", "busybox", "base64", "python3", "perl"]);
DeviceProcessEvents
| where Timestamp > ago(30d)
| where InitiatingProcessFileName in~ ("node", "node.exe", "bun")
| where FileName in~ (ShellOrRecon)
| where not(ProcessCommandLine has_any ("npm ", "npx ", "yarn ", "pnpm ", "node-gyp", "git "))
| project Timestamp, DeviceName, AccountName, InitiatingProcessCommandLine, FileName, ProcessCommandLine
| order by Timestamp desc

A production web server whose Node.js process runs whoami, id, uname, curl or wget should be investigated straight away.

Hunt 2: files written to temporary folders by Node.js and then run

// Example: Defender for Endpoint, files dropped by Node.js into temp folders and executed within an hour
let Drops = DeviceFileEvents
    | where Timestamp > ago(30d)
    | where ActionType == "FileCreated"
    | where InitiatingProcessFileName in~ ("node", "node.exe") or InitiatingProcessParentFileName in~ ("node", "node.exe")
    | where FolderPath has_any ("/tmp/", "/var/tmp/", "/dev/shm/", @"\AppData\Local\Temp\", @"\Windows\Temp\")
    | project DropTime=Timestamp, DeviceId, FolderPath, SHA256;
DeviceProcessEvents
| where Timestamp > ago(30d)
| join kind=inner Drops on DeviceId, FolderPath
| where Timestamp between (DropTime .. DropTime + 1h)
| project DropTime, Timestamp, DeviceName, FolderPath, SHA256, ProcessCommandLine, InitiatingProcessFileName
| order by DropTime desc

Hunt 3: Node.js reaching cloud metadata, tunnels or unusual ports

// Example: Defender for Endpoint, outbound connections from Node.js that fit post-exploitation
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where InitiatingProcessFileName in~ ("node", "node.exe") or InitiatingProcessParentFileName in~ ("node", "node.exe")
| where RemoteIP == "169.254.169.254"
    or RemoteUrl has_any ("trycloudflare.com", "anondns.net", "ngrok", "pastebin.com", "ghostbin")
    or (ActionType == "ConnectionSuccess" and RemoteIPType == "Public" and RemotePort !in (80, 443))
| summarize Connections=count(), Ports=make_set(RemotePort, 10), Urls=make_set(RemoteUrl, 10),
            FirstSeen=min(Timestamp), LastSeen=max(Timestamp)
    by DeviceName, InitiatingProcessFileName, RemoteIP
| order by FirstSeen desc

Cloud SDKs call the metadata address legitimately, so compare against a baseline. A first-time metadata call, a tunnel domain or a raw IP on a high port right after a burst of POST requests is the pattern to chase.

Hunt 4: secret hunting under Node.js

// Example: Defender for Endpoint, credential and secret collection commands launched from Node.js
DeviceProcessEvents
| where Timestamp > ago(30d)
| where InitiatingProcessFileName in~ ("node", "node.exe") or InitiatingProcessParentFileName in~ ("node", "node.exe")
| where ProcessCommandLine has_any ("printenv", "/proc/self/environ", ".env", "trufflehog", "gitleaks",
    "169.254.169.254", "metadata.google.internal", "/var/run/secrets/kubernetes.io",
    "get-access-token", "sts get-caller-identity", ".aws/credentials", "authorized_keys")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, ProcessCommandLine
| order by Timestamp desc

Hunt 5: Defender alerts already raised on web servers

Microsoft added detections for React2Shell exploitation in December 2025. They also fire on the generic Node.js behavior that new exploits produce.

// Example: Defender XDR, alerts tied to React Server Components exploitation and Node.js abuse
AlertInfo
| where Timestamp > ago(90d)
| where Title has_any ("React Server Components", "React2Shell", "Node.js", "network service", "reverse shell", "cryptocurrency miner")
| join kind=inner (AlertEvidence | where EntityType == "Machine" | project AlertId, DeviceName) on AlertId
| summarize Alerts=make_set(Title, 10), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by DeviceName, Severity
| order by LastSeen desc

Hunt 6: bursts of failing POST requests on Azure App Service

Failed exploit attempts often leave a run of POST requests that end in server errors from one source.

// Example: Sentinel, Azure App Service HTTP logs, sources with many POSTs ending in 5xx errors
AppServiceHTTPLogs
| where TimeGenerated > ago(14d)
| where CsMethod == "POST"
| summarize Requests=count(), Errors=countif(ScStatus >= 500), Paths=make_set(CsUriStem, 10),
            FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated)
    by CIp, _ResourceId, bin(TimeGenerated, 1h)
| where Errors >= 5 and Errors * 2 >= Requests
| order by Errors desc

For self-hosted servers behind a reverse proxy, run the same logic over the proxy’s access logs. React2Shell exploit requests carried a next-action or rsc-action-id header, according to Amazon’s threat intelligence team; log those headers at the proxy if you can.

Responding to a possible compromise

  1. Preserve evidence first: a copy of the container or VM disk, the web and proxy logs, and the Node.js process list and network connections.
  2. Isolate the server or scale the deployment to zero, then redeploy from a clean, patched build. Do not clean a compromised container in place.
  3. Rotate every secret the application could read: environment variables, .env files, cloud instance roles, database passwords, API keys for AI and payment services, and Kubernetes service account tokens.
  4. Look for persistence on VMs: new users, changed ~/.ssh/authorized_keys, cron jobs, systemd services, remote management agents (MeshAgent was used after React2Shell), and files in /tmp, /var/tmp and /dev/shm.
  5. Check the cloud account for API calls made with the application’s credentials from unfamiliar addresses, and for new access keys, users or compute instances, especially miners.

Indicators of compromise

None have been published for GHSA-xqc2-xf4c-x3h3 or CVE-2026-96889. The indicators below are from React2Shell exploitation in December 2025, published by Microsoft and Amazon. They are useful when checking whether an application that missed the December 2025 patches was already compromised. Infrastructure from late 2025 is likely to have changed.

Type Indicator Context
IP 194.69.203[.]32 Command and control, React2Shell exploitation (Microsoft)
IP 162.215.170[.]26 Command and control (Microsoft)
IP 216.158.232[.]43 Command and control (Microsoft)
IP 196.251.100[.]191 Command and control (Microsoft)
IP 46.36.37[.]85 Command and control (Microsoft)
IP 92.246.87[.]48 Command and control (Microsoft)
IP 183.6.80[.]214 Exploitation source, December 4, 2025 (Amazon)
Domain anywherehost[.]site Command and control (Microsoft)
Domain xpertclient[.]net Command and control (Microsoft)
Domain superminecraft.net[.]br Payload host (Microsoft)
Domain donaldjtrmp.anondns[.]net, labubu.anondns[.]net, krebsec.anondns[.]net Command and control (Microsoft)
Domain *.trycloudflare[.]com Cloudflare Tunnel endpoints used for payload downloads (Microsoft)
HTTP next-action or rsc-action-id header on POST, body containing $@ or "status":"resolved_model" React2Shell exploit requests (Amazon)

Timeline

  • November 29, 2025: Lachlan Davidson reports React2Shell to Meta’s bug bounty program.
  • December 3, 2025: React releases 19.0.1, 19.1.2 and 19.2.1 and publishes CVE-2025-55182. Next.js publishes its own advisory and patched releases.
  • December 3 to 4, 2025: Amazon observes exploitation attempts within hours of disclosure.
  • December 4, 2025: ASD’s ACSC publishes a critical alert for Australian organizations.
  • December 5, 2025: CISA adds CVE-2025-55182 to its Known Exploited Vulnerabilities catalog, with a due date of December 12. Microsoft sees exploitation from the same day.
  • December 11, 2025: React fixes two denial-of-service flaws and a source code exposure (CVE-2025-55184, CVE-2025-67779, CVE-2025-55183).
  • December 15, 2025: Microsoft reports several hundred compromised machines, most running cryptominers.
  • January to July 2026: React fixes further denial-of-service flaws in React Server Components (CVE-2026-23864, CVE-2026-23869, CVE-2026-23870, CVE-2026-44907).
  • September 23, 2026: CVE-2026-96889 is published for librsvg. sharp 0.35.5 follows on September 27.
  • October 8, 2026: Next.js announces an out-of-band update for two critical and one high-severity upstream issues.
  • October 14, 2026: React publishes GHSA-xqc2-xf4c-x3h3 and releases 19.0.9, 19.1.10, 19.2.9 and 19.3.1. Next.js releases 16.4.1 and 15.5.28 with GHSA-673q-mjm6-r5xr and CVE-2026-96889.
  • October 17, 2026: A public repository claiming proof-of-concept code for the Next.js use cache flaw appears.
  • November 3, 2026: Next.js releases 16.4.5 and 15.5.29 with seven further fixes.
  • November 8, 2026: A second public repository claims a working proof of concept and test lab for GHSA-xqc2-xf4c-x3h3.

Frequently Asked Questions

Is this React2Shell again? No. React2Shell (CVE-2025-55182) was fixed in December 2025. GHSA-xqc2-xf4c-x3h3 is a new flaw in the same part of React, fixed on October 14, 2026. Versions that fix React2Shell are still vulnerable to the new one.

Why is there no CVE? React published the advisory through GitHub without a CVE ID. Track it by its GHSA ID, which GitHub Dependabot, npm audit and most dependency scanners recognize.

We use Next.js but not Cache Components. Do we still need to upgrade? Yes. Next.js advises upgrading even without use cache functions that return typed arrays, and the same release fixes the critical image optimization flaw and a denial of service in Server Actions.

We use the Pages Router only. Are we affected? Not by the React Server Components flaw. You are still exposed to the image optimization flaw on glibc Linux until you run Next.js 15.5.28 or later with sharp 0.35.5 or later.

Is a site hosted on Vercel or Netlify safe? The platforms can add protective rules, but they do not change your application code. React and Vercel both say to upgrade regardless of hosting.

Is it being exploited? No exploitation has been reported by React, Vercel or CISA. Public repositories claim proof-of-concept code, and React2Shell was exploited within hours of disclosure, so assume scanning is under way.

We upgraded react and react-dom. Is that enough for Next.js? No. Next.js ships its own compiled copy of the React server packages. Upgrade next itself to 16.4.5 or 15.5.29.

Our Next.js line is 15.3 or 16.2. Is there a patch? No. Fixes were released only for 16.4 (Active LTS) and 15.5 (Maintenance LTS). Move to 16.4.5 or 15.5.29.

How ThreatDefence is responding

ThreatDefence has added GHSA-xqc2-xf4c-x3h3, GHSA-673q-mjm6-r5xr and CVE-2026-96889 to our vulnerability intelligence. Where we hold endpoint, cloud and web telemetry, our SOC is:

  • identifying internet-facing Node.js and Next.js servers and containers, and the versions they run
  • alerting on Node.js processes that start shells, download files, read secrets or connect to tunnels and cloud metadata
  • re-checking servers that missed the December 2025 React2Shell patches for signs of earlier compromise

If you run React or Next.js applications and want help checking them or investigating suspicious activity, contact us. Read more about our managed detection and response.

Sources

Need help checking your environment for this issue? Talk to the ThreatDefence SOC.Talk to Our SOC

Talk to Our SOC

Questions about this advisory or help checking your environment.

    I'm an MSP, MSSP, or reseller

    By submitting this form, you accept the terms in our privacy policy.