Is React2Shell More Than a Next.js Problem?

The recent disclosure of CVE-2025-55182, a critical Remote Code Execution (RCE) vulnerability within React, has sent significant shockwaves throughout the web development and cybersecurity industries, forcing an urgent re-evaluation of security postures for countless applications. Dubbed “React2Shell,” this vulnerability allows malicious actors to circumvent security boundaries and execute arbitrary code on a server by exploiting a fundamental flaw in the way React Server Components (RSC) handle input deserialization. While initial reports and remediation efforts have overwhelmingly focused on Next.js, a consequence of its immense popularity and default exposure to the vulnerability, deeper analysis reveals that the issue is not confined to a single framework. Instead, it points to a more profound problem rooted in the core mechanics of RSC payload processing, with far-reaching implications that extend well beyond the Vercel ecosystem. Understanding the technical intricacies of this exploit is therefore critical, not just for teams patching a Next.js application, but for anyone architecting a custom React server, utilizing alternative RSC-compatible frameworks, or defending the cloud-native workloads where these applications are deployed.

1. A Surge of Exploitation in the Wild

Following the vulnerability’s public disclosure, a rapid and widespread wave of opportunistic exploitation began, with threat actors quickly pivoting from simple reconnaissance to aggressive, hands-on-keyboard abuse within cloud-native environments. The primary targets have been internet-facing Next.js applications and other containerized workloads running in managed cloud services and Kubernetes clusters. In numerous observed incidents, attackers successfully leveraged the vulnerability to gain an interactive shell inside application containers, such as those hosting Next.js frontends. From this initial foothold, a consistent pattern of post-exploitation activity has emerged. Attackers immediately commence environment and identity discovery by executing commands like whoami and hostname, dumping all available environment variables, and enumerating system files like /etc/passwd. These commands are often consolidated into one-liners and their output is exfiltrated to attacker-controlled infrastructure using simple tools like curl or nc. A significant amount of this activity involves DNS-based beaconing, where extensive use of oast domains and similar callback infrastructure is employed not only to confirm successful code execution and network egress from the compromised cloud workload but also to fingerprint the target environment by embedding application-specific hostnames and URLs into the callbacks, going far beyond the needs of simple scanning. In several more advanced cases, the exploit chain escalated from these initial connectivity checks to the establishment of fully interactive reverse shells, connecting directly from the Node.js or Next.js process to external command-and-control (C2) servers.

Once initial access was established, multiple attack campaigns demonstrated a strong and immediate focus on harvesting cloud and developer credentials to facilitate lateral movement and further compromise. One actor, after gaining a reverse shell, systematically executed scripts to dump configuration and credential data related to npm, AWS, Docker, Git, and SSH, carefully encoding all harvested information in Base64 for covert exfiltration. A separate, more sophisticated campaign deployed a Base64-encoded script designed for comprehensive secret scraping. This script first parsed environment variables for any secrets related to cloud providers or applications, searching for common patterns like AWS, TOKEN, SECRET, PASS, and DB_. It then recursively scanned critical filesystem paths—including /home, /root, /etc, and /var/www—for sensitive configuration files and key material such as .env files, JSON and YAML configs, and SSH keys, while intelligently avoiding large or noisy files that might trigger detection. Most notably, this script attempted to access the cloud instance metadata service at 169.254.169.254 to retrieve temporary IAM credentials, indicating a clear and deliberate intent to escalate privileges within the cloud environment. Another large, standalone shell script observed in the wild performed broad secret harvesting at scale, targeting common developer paths like .ssh, .aws, .kube, and .config/gcloud, as well as cryptocurrency wallet locations. This script bundled its findings into a single report file and uploaded it via an HTTP POST request to an attacker-controlled server, demonstrating a clear trend of treating compromised containers as valuable collection points for credentials that unlock access to both cloud control planes and adjacent developer infrastructure.

2. From Monetization to Persistence

Alongside credential theft, several distinct campaigns have leveraged CVE-2025-55182 for direct monetization by deploying cryptomining software within compromised cloud workloads. One such campaign dropped a UPX-packed variant of the XMRig miner and utilized custom infrastructure to distribute shell scripts with multiple functions. These scripts were designed not only to deploy the miner but also to eliminate competition by killing processes associated with other miners. Furthermore, they attempted local privilege escalation using known vulnerabilities like CVE-2021-4034 to gain greater control over the container. To evade detection, the mining process was often masqueraded as a plausible system service, such as systemd-devd, helping it blend into the container’s process list. Another, less sophisticated campaign simply pulled a stock version of XMRig from its public GitHub repository, configured it with attacker-controlled mining pools, and executed it from a writable directory like /tmp. In more advanced activity, threat actors retrieved installer scripts from mining pools such as c3pool and executed them via an interactive shell. This approach wired the cryptominer to specific Monero wallets and used persistence mechanisms like nohup /var/tmp/crond to ensure the miner would continue running as a disguised background process inside the container. Several of these campaigns appear to be multi-tenant, reusing the same family of scripts and C2 infrastructures across different victim organizations and cloud clusters, indicating a streamlined and scalable operation.

Beyond immediate financial gain through cryptomining, at least one campaign has demonstrated a more strategic objective by deploying a fully-featured backdoor to establish long-term persistence. In these incidents, attackers first used the React2Shell vulnerability to download initial shell scripts from a dynamic DNS host. These dropper scripts, in turn, fetched Sliver payloads—64-bit ELF binaries—and executed them from temporary file locations. Sliver is a powerful and versatile post-exploitation framework that provides attackers with extensive capabilities for command and control, lateral movement, and data exfiltration. The observed Sliver implants communicated with an external C2 infrastructure over IP addresses that reused TLS certificates and domains across multiple samples, suggesting a dedicated and well-maintained attacker ecosystem rather than the use of opportunistic, commodity malware. This activity represents a significant escalation from the “smash-and-grab” tactics of cryptomining and credential harvesting. It signals a shift toward establishing long-term, operator-driven access inside compromised cloud workloads, allowing for more patient and targeted post-exploitation activities. The clear pattern emerging from this activity shows that attackers are using CVE-2025-55182 not just to execute one-off commands, but to gain interactive, cloud-aware access to containerized environments, aggressively harvest secrets, weaken local defenses, and deploy persistent backdoors for future operations.

3. The Vulnerability’s True Scope

A critical aspect of CVE-2025-55182 that has been underrepresented in much of the initial coverage is its applicability to platforms beyond Next.js that also utilize React Server Components. The intense focus on Next.js was largely due to two key factors. First, it is by far the most popular and widely adopted framework that uses the RSC feature, making it the largest potential attack surface. Second, and more importantly, the RSC feature is not only enabled but also exposed by default on all Next.js applications, regardless of their specific configuration. This second point is crucial as it explains the immediate potency of the public proof-of-concept. Any Next.js application, whether it explicitly defines Server Actions or not, has the vulnerable data flow accessible. An attacker simply needs to add the next-action header to an HTTP request to have their malicious payload parsed by the vulnerable deserialization logic. There is no need to guess or discover a valid action name or a specific application endpoint, which dramatically lowers the barrier to exploitation. This “default open” posture made Next.js an easy and obvious primary target for security researchers and malicious actors alike. Because of this ease of exploitation, other platforms where the vulnerable flow is reached through a different, less direct mechanism may have been excluded from the initial conversation, but they remain extremely vulnerable to the same underlying flaw.

While Next.js served as the initial proving ground for React2Shell exploits, the vulnerability is not exclusive to it. Internal research has confirmed that code execution can be achieved with only minor adjustments to the public proof-of-concept on other frameworks that leverage RSC, including Waku and Vite (when used with the RSC Plugin). It is highly probable that more frameworks integrating this technology are also susceptible and would require only trivial modifications to be exploited. In a custom, or “native,” React setup where a developer has architected their own server to support RSC, the attack vector changes but the vulnerability persists. In this scenario, the vulnerable decoding logic is only invoked if the developer has explicitly created a server endpoint to receive and process RSC payloads. Therefore, an attacker must first identify this specific, custom endpoint before they can submit a malicious payload. However, once that endpoint is found, any application using the vulnerable versions of the underlying React packages is susceptible to the same RCE exploit. This implies that effective detection of vulnerable servers must be holistic. It cannot rely solely on dynamic scanners that use the current PoCs targeting the Next.js next-action header. A comprehensive strategy must also include static code analysis and on-disk validation that can detect the presence of vulnerable packages in lesser-known platforms or custom React implementations, ensuring that the entire at-risk ecosystem can be identified and secured.

4. Unpacking the Proof of Concept

The React2Shell vulnerability is exploited through the improper input deserialization of RSC form data payloads, where a lack of type checking at critical junctures allows an attacker to substitute legitimate objects with malicious, attacker-controlled “gadgets.” By crafting a payload with a complicated structure of self-references, an attacker can ultimately achieve Remote Code Execution. The proof-of-concept payload works by assembling these gadgets during the deserialization process. The primary RCE gadget is the native Function() constructor, which behaves similarly to eval() by creating a callable function from a provided string of JavaScript code. The payload accesses this constructor through a clever chain: it defines an empty array, accesses its constructor property (which is Array), and then accesses that object’s constructor property, which resolves to Function(). This Function() gadget is then assigned to the _formData.get property of a crafted object designed to mimic an internal Response object. The malicious JavaScript code to be executed, such as 'console.log(7*7+1)//', is placed in another property of this fake object, _prefix. Another part of the payload, identified as Chunk 2, is marked as a Promise object. This is a critical step that ensures the code will be executed later in the process via the .then method. Finally, a master object, Chunk 1, is created to look like a legitimate Chunk object but is designed to reference the attacker’s crafted Response object, tying all the malicious components together and setting the stage for the exploit execution.

The exploit is triggered as the server’s deserialization logic processes the malicious payload. The sequence begins when parsing starts with the initial reference, '0': '$1', which leads the deserializer to resolve the attacker’s crafted Chunk 1. In resolving Chunk 1, the logic is forced to resolve its _response property, which points to the fake Response object (Chunk 4). It is during this step that the gadget injection occurs: the deserializer’s internal state is manipulated so that the _formData.get property is overwritten with the Function() gadget, and the _chunks property is correctly linked to maintain the deserialization context. The core of the exploit lies in the value property of Chunk 1, which contains a nested JSON object specifically designed to trigger a promise chain: '{"then":"$3:map","0":{"then":"$B3"},"length":1}'. When the innermost reference, $B3, is processed, it hits the vulnerable code snippet within the React library. At this point, the response object in the code is the attacker’s crafted Chunk 4. The vulnerable call effectively becomes Chunk_4._formData.get(Chunk_4._prefix + obj), which translates into the execution of Function('console.log(7*7+1)//' + obj). This action creates a new, anonymous function containing the attacker’s arbitrary code. This function is then returned up the promise chain and is ultimately invoked by the .then resolutions that were set up earlier, resulting in the successful execution of the attacker’s code on the server.

5. A Broader Perspective on Component Security

The rapid and widespread exploitation of CVE-2025-55182 served as a critical reminder of the security risks inherent in modern web architectures, particularly those involving server-side rendering and the complex deserialization of component data. This event forcefully underscored the necessity for development and security teams to look beyond high-level framework security and instead perform deeper scrutiny of the underlying libraries and architectural patterns they adopt. The vulnerability was a stark demonstration that even trusted, foundational components could be transformed into potent attack vectors if their handling of untrusted input was not rigorously validated at every step. It revealed a blind spot in how the industry had approached the security of server components, where the convenience of state transfer between client and server had inadvertently created an opening for sophisticated injection attacks. The incident prompted an immediate and necessary re-evaluation of default security postures across the ecosystem. The astonishing ease of exploitation in Next.js, directly attributable to its “default open” server action endpoint, highlighted a critical lesson in platform design: the immense importance of implementing secure-by-default configurations. The key takeaway was a fundamental shift in mindset. Moving forward, the industry learned the value of forcing developers to explicitly opt into potentially dangerous features rather than requiring them to discover and manually disable them. The incident catalyzed a renewed focus on comprehensive dependency scanning, robust input validation, and, most importantly, a deeper architectural understanding of how data flows and transforms between the client and the server.

subscription-bg
Subscribe to Our Weekly News Digest

Stay up-to-date with the latest security news delivered weekly to your inbox.

Invalid Email Address
subscription-bg
Subscribe to Our Weekly News Digest

Stay up-to-date with the latest security news delivered weekly to your inbox.

Invalid Email Address