When CVE-2025โ€“55182 dropped, it immediately became one of the most impactful Remote Code Execution (RCE) vulnerabilities in the JavaScript ecosystem. The issue affected Next.js 13+, specifically a feature called Server Actions, which quietly introduced a dangerous deserialization bug.

In this blog post, I'll try break down CVE-2025โ€“55182 from scratch what caused it, how to identify it in real-world applications, how to test it, and what developers need to keep the applications safe. Whether you're a pentester, developer, or security enthusiast, this write-up will make you fully understand how this vulnerability works and how to detect it.

Free Link For Non Members โœŒ๏ธ

Understanding Next.js

Next.js is a framework built on React. In newer versions (13+), Next.js introduced Server Actions.

What is Server Actions?

They allow you to write a server-side function directly inside your React component:

async function addUser(data) {
  // runs on the server
}

Instead of building an API endpoint, the browser automatically sends a special POST request that triggers these functions. These requests are not normal JSON APIs. They use something called the React Server Components protocol (RSC/Flight). This "special" request structure is the root of the vulnerability.

What is the vulnerability?

None
Image Credit โ€” Endor Labs

The core problem here is Next.js blindly trusts special form-data fields sent by the browser and deserializes them without proper validation. This leads to Unsafe Deserilization > Remote Code Execution (RCE). Which means a crafted request can force the server to run attacker-controlled code. But this only works if the request is processed as a Server Action.

So as a pentester or bug bounty hunter, first goal is to find where server actions are being used.

How a vulnerable request looks?

A vulnerable server action request always has three mandatory signs:

  1. Header:
Next-Action: <some_action_id>

2. Content-Type: multipart/form-data (If youu see JSON then it is not a server action and it is not vulnerable.

3. Body contains a field named 0 with a value that starts with: ["$ACTION_... For example 0=["$ACTION_abc123",{"user":"paradox"}]

If all 3 appear in the reuqst then the endpoint is potentially vulnerable. If any of the 3 is missing then it is not vulnerable.

Also you check the vulnerable Next.js version from tools like whatweb or wappalyzer.

If the target application make any requests that contain Next-Action: then you can test this vulnerability there. Simple :)

Approach to find

  1. Open developer tools then go in network filter only POST requests. Because Server Actions use POST.
  2. Now you see only POST request, open each requests and check for header Next-Action... If this header exists continue testing if not exist skip that request.
  3. Check for the Content-Type, If it shows Content-Type: multipart/form-data continue with the testing if it showing application/json or something else skip it.
  4. Then expand the request and look for filed 0=["$ACTION_.. This is the server action endpoint and our target. This is the exact pattern that triggers the vulnerability.

Safe Approach

Once you find a server action request. Replace the 0= value with malformed data. For example 0=["$ACTION_XXXX","hehehe"] So here we are not executing anything harmful just checkinf if the server crashes while parsing.

If trhe server returns 500 Internal Server Error or error messages like:

Invalid Flight Payload Unexpected Server Action Decode Error Deserilization Failed

The endpoint is vulnerable.

If the server responds normally then the app is not vulnerable or the app is patched.

Remote Code Execution

Inside the field 0= it normally contains some $ACTION ID and user inputs. But due to the deserilization vulnerability. Next.js will treat certain serlialized objects as executable server-side callbacks.

So replace the filed with a payload that tells hte Next.js: When you deserilize this, call the function and run a system command.

For example:

POST /some-endpoint HTTP/1.2
Host: something.com
Next-Action: abcde12345
Content-Type: multipart/form-data;

---------abc
Content-Disposition: form-data; name="0"

0=["$ACTION_123ABC",
   {
     "$function": "child_process.execSync",
     "args": ["whoami"]
   }
 ]
---------abc

The response will contain the output of the command if the server is vulnerable.

Behind The Scenes

Next.js tries to deserialize the value inside the 0 field: ["$ACTION_XXXX","hehehe"] This triggers the internal RSC parser. If the server is unpatched it accepts the string, processes it unsafely and it leads to RCE.

Mitigations

The only guaranteed fix is to update Next.js to a version where the vulnerable deserialization code was patched.

Versions that are safe:

15.0.5 15.1.9 15.2.6 15.3.6 15.4.8 15.5.7 15.6.0-canary.58 16.0.7

References:

https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components

Outro

So that's all for this post!

We learned what Next.js is, how this new CVE-2025โ€“55182 vulnerability works, how to find it, how to safely exploit it, and how to fully mitigate it.

If you found this guide helpful, a like or share would mean a lot ๐Ÿ˜Š๐Ÿ‘