Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-55182-analysis | Kitploit
Tools/GitHubGitHub/santihabib/cve-2025-55182-analysis
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & Education
GitHubsantihabib/cve-2025-55182-analysis

CVE-2025-55182-analysis

View Repository
48 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Technical Analysis of CVE-2025-55182: My Research Journey

⚠️ Important Disclaimer

This document describes my personal research process into CVE-2025-55182, including confirmed findings and experiments I carried out. This represents an honest account of my investigation, including initial incorrect assumptions and the eventual breakthrough.


Executive Summary

After an extensive investigation into CVE-2025-55182 (CVSS 10.0), my initial conclusion was that automatic RCE had not been publicly demonstrated and that exploitation required application-specific gadgets. This conclusion was incorrect.

On December 5, 2025, after receiving additional insights from another independent researcher on X (@maple3142), I successfully reproduced full unauthenticated RCE on vanilla Next.js without requiring any application-specific code vulnerabilities.


Research Methodology

Phase 1: Patch Analysis (Initial Incorrect Assumption)

My initial focus was on the first change in the React 19.0.1 patch:

Vulnerable (19.0.0):

root@kitploit:~
return fn.bind.apply(fn, [null].concat(_ref));

Patched (19.0.1):

root@kitploit:~
if (Array.isArray(promiseValue)) {
  promiseValue = promiseValue.slice(0);
} else {
  promiseValue = [];
}

I assumed the attack path was through fn.bind.apply() with malicious objects instead of arrays. I was able to demonstrate argument injection into Server Actions using $ACTION_REF_ with attacker-controlled bound:

root@kitploit:~
curl -X POST http://localhost:9000/ \
  -F '$ACTION_REF_0=' \
  -F '$ACTION_0:0={"id":"<ACTION_ID>","bound":["; id #","/etc/passwd"]}'

Result: The arguments were successfully injected into the Server Action. However, this only leads to RCE if the target function uses those arguments unsafely.


Phase 2: Unsafe Behavior Observed in the Patch

A deeper look at the patch revealed another important change in getOutlinedModel():

Vulnerable:

root@kitploit:~
for (key = 1; key < reference.length; key++)
  parentObject = parentObject[reference[key]];

Patched:

root@kitploit:~
if (hasOwnProperty.call(value, name)) {
  value = value[name];
}

This vulnerable behavior allowed prototype-chain traversal using references like:

root@kitploit:~
$1:__proto__:constructor:constructor

Phase 3: Experiment with Thenable and Function.constructor (Dead End)

During the research, I tested a thenable object containing a .then property:

root@kitploit:~
{"then": "$1:__proto__:constructor:constructor"}

When JavaScript processes this through await:

  1. JavaScript sees a .then property and treats the object as a Promise
  2. Calls obj.then(resolve, reject)
  3. If then resolves to Function.constructor, JavaScript attempts to execute Function(resolve, reject)

Observed result:

root@kitploit:~
SyntaxError: Unexpected token 'function'
    at Object.Function [as then] (<anonymous>)

Phase 4: The Argument Binding Limitation (The Wall)

When Function.constructor is invoked as:

root@kitploit:~
Function(resolve, reject)
// resolve.toString() = "function () { [native code] }"
// Function attempts to parse this as code → SyntaxError

The arguments resolve and reject are always the native Promise functions. Function attempts to interpret the first argument as source code, which is invalid JavaScript.

This is where my research stalled. I concluded that controlling arguments to Function.constructor was impossible without an application-specific gadget.


Phase 5: The Breakthrough — Blob Deserialization (December 5, 2025)

After publishing my initial findings, another independent researcher pointed me to a critical piece I had missed: the $B (Blob) deserialization sink.

The Missing Piece

In the compiled React Flight server code (not visible in TypeScript sources), there exists:

root@kitploit:~
case "B":
  return response._formData.get(response._prefix + id);

Location:

  • Package: [email protected]
  • File: cjs/react-server-dom-webpack-server.node.unbundled.development.js
  • Also in: [email protected]/dist/compiled/react-server-dom-webpack/

This code allows React to call response._formData.get() with values derived from attacker-controlled input, without validation.

Why This Changes Everything

ApproachArguments to Function.constructorResult
Thenable (Phase 3)resolve, reject (native functions)❌ SyntaxError
Blob + Poisoned Response_prefix (attacker-controlled string)✅ RCE

By combining:

  1. Prototype traversal ($1:__proto__:then → Chunk.prototype.then)
  2. A poisoned _response object with:
    • _formData.get set to Function.constructor
    • _prefix set to arbitrary JavaScript code
  3. An inner model containing $B reference

The case "B": handler executes:

root@kitploit:~
Function.constructor("<attacker code>" + id)

This bypasses the argument binding limitation entirely.


Public PoCs: Analysis

Popular GitHub PoCs claiming RCE use Action IDs such as:

  • "child_process#execSync"
  • "vm#runInThisContext"

These are fake. Next.js only accepts Action IDs defined by the application. Invalid IDs produce:

root@kitploit:~
TypeError: Cannot read properties of undefined (reading 'workers')

However, the real exploit does not require fake Action IDs. Any valid Server Action ID works.


Verification and Impact

I tested this exploitation chain on a minimal Next.js 15.0.3 + React 19.0.0 application with only:

root@kitploit:~
async function myAction(data) {
  "use server";
  console.log("Server Action called with:", data);
  return { success: true, received: data };
}

Result: Full RCE confirmed. The application contained no unsafe code, no eval, no execSync, no gadgets.

Impact Assessment


Critical Discovery: Patch Status

As of December 5, 2025, the $B sink still exists in Next.js 15.0.5 (the supposedly patched version).

Verification:

root@kitploit:~
$ npm pack [email protected]
$ tar -xzf next-15.0.5.tgz
$ grep -A5 'case "B":' package/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-server.node.development.js

Result:

root@kitploit:~
case "B":
  return response._formData.get(response._prefix + obj);

The code is identical to the vulnerable version.


Responsible Disclosure Note

Due to the discovery that the vulnerability may not be fully patched in the claimed "fixed" versions, I am withholding the complete proof-of-concept payload pending verification with the security teams at Vercel and Meta.

The technical details provided in this document are sufficient to understand the vulnerability mechanism but intentionally incomplete to prevent immediate exploitation.


Updated Conclusions

What I Found (Phases 1-4)

TechniqueStatus
Argument injection via bound✅ Confirmed (limited impact)
Prototype traversal

What I Missed Initially

IssueImpact
The $B (Blob) deserialization sink❌ Critical - enables argument control
Examining compiled vs. source code❌ The sink only exists in compiled output
Response object poisoning mechanism❌ Allows bypassing all protections

Final Assessment

CVE-2025-55182 is exploitable for full unauthenticated RCE on vanilla Next.js applications.

  • ✅ No application-specific gadget required
  • ✅ Works with a single HTTP POST
  • ✅ The "gadget" is built into React's deserialization logic
  • ⚠️ May not be fully patched in claimed fixed versions

Timeline

  • December 3, 2025: Analysis of prototype traversal and thenable approach (dead end)
  • December 4, 2025: Received insight about $B deserialization from independent researcher
  • December 5, 2025: Full RCE reproduction confirmed
  • December 5, 2025: Discovered vulnerability may persist in "patched" versions
  • December 5, 2025: This report published (with PoC details withheld)

Recommendations

  1. Update immediately to the latest versions of React and Next.js
  2. Verify the patch by testing if $B deserialization still accepts arbitrary _response objects
  3. Monitor for exploitation attempts - look for:
    • Unusual Next-Action headers
    • Complex multipart payloads with $@, __proto__, $B patterns
  4. Consider WAF rules to block suspicious patterns in Server Action requests
  5. Contact security teams if you're running affected versions in production

Acknowledgments

  • The breakthrough insight regarding $B deserialization was provided by an researcher on X (@maple3142)
  • The React and Next.js security teams for their work on patches (ongoing verification)
  • The security research community for collaborative investigation

Lessons Learned

  1. Examine compiled code, not just sources - Critical vulnerabilities can hide in bundled output
  2. Revisit assumptions when new information emerges
  3. Collaborative research is essential for complex vulnerabilities
  4. Document the journey - Dead ends are valuable for understanding the full picture
  5. Responsible disclosure takes precedence over public recognition

Last Updated: December 5, 2025

Download Tool
AspectFinding
Authentication required?❌ No
Application gadget required?❌ No
Works on vanilla Next.js?✅ Yes
Number of requests needed1 POST
Affected versionsNext.js ≤15.0.4 + React 19.0.0
CVSS Score10.0 (justified)
✅ Confirmed
Access to Function.constructor via thenable✅ Confirmed (but not exploitable alone)
Detection of vulnerable versions✅ Confirmed