Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
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 — Detailed technical analysis and proof-of-concept exploit for CVE-2025-55182, a critical RCE vulnerability in React's Flight Protocol. Covers path traversal, fake chunk injection, and WAF bypass techniques. | Kitploit
Tools/GitHubGitHub/hulh122/cve-2025-55182
Vulnerability AnalysisExploitationWeb Application ExploitationWAF BypassLearning & EducationPayload Development
GitHubhulh122/cve-2025-55182

CVE-2025-55182

Detailed technical analysis and proof-of-concept exploit for CVE-2025-55182, a critical RCE vulnerability in React's Flight Protocol. Covers path traversal, fake chunk injection, and WAF bypass techniques.

View Repository
199 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

CVE-2025-55182 - React Server Components RCE

NOTE: Written by AI/Claude

https://github.com/ejpir/CVE-2025-55182-bypass

TL;DR

CVE-2025-55182 is a critical RCE vulnerability in React's Flight Protocol. The attack chains path traversal + fake chunk injection + $B handler abuse to execute Function(attacker_code).

Big thanks to maple3142 for the working exploitation chain!


The Exploit

Attack Overview

The exploit uses three form fields to construct a malicious payload:

  1. Creates a fake chunk object with self-referential then (field 1 $@0 → field 0)
  2. Embeds a fake _response with _formData.get set to $1:constructor:constructor
  3. Triggers the $B handler which calls response._formData.get(response._prefix + id)
  4. Path traversal resolves _formData.get → Function, executing Function(code)

Exploitation Flow

┌─────────────────────────────────────────────────────────────────────┐
│  1. Attacker sends multipart form with fake chunk object            │
│     → decodeReply() parses form fields 0, 1, 2                      │
│     → Object has: then, status, value, _response                    │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│  2. Self-reference makes object thenable with real function         │
│     → then: "$1:__proto__:then" → Chunk.prototype.then              │
│     → Chunk.prototype.then(this) calls initializeModelChunk(this)   │
│     → Uses this._response (attacker's fake _response)               │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│  3. parseModelString() handles "$B1337" reference                   │
│     → case "B": return response._formData.get(response._prefix+id)  │
│     → Calls _formData.get with attacker's _prefix + "1337"          │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────┐
│  4. getOutlinedModel() resolves _formData.get (lazy evaluation):    │
│     → "$1:constructor:constructor" traverses prototype chain        │
│     → Returns Function constructor                                  │
│     → Function(code + "1337") → RCE                                 │
└─────────────────────────────────────────────────────────────────────┘

Key Components

ComponentPurpose
then: "$1:__proto__:then"Self-referential thenable; chunk 1 ($@0) points back to chunk 0
status: "resolved_model"Makes object appear as valid React chunk
reason: -1Sets rootReference to undefined (avoids reference conflicts)
value: '{"then":"$B1337"}'Nested payload that triggers $B handler
_response._prefixContains the RCE code string
_response._chunks: "$Q2"Empty Map to prevent crashes during chunk processing
_response._formData.getPoints to Function via $1:constructor:constructor

Component Deep Dive

Form Field Structure

The exploit uses three form fields with circular references:

Field 0: {"then":"$1:__proto__:then", "status":"resolved_model", ...}
Field 1: "$@0"    ← references back to field 0
Field 2: []       ← empty array for _chunks Map

Self-Referential Thenable (then)

The then: "$1:__proto__:then" creates a self-reference that resolves to a real function:

$1:__proto__:then
  ↓
$1 → chunk 1 → "$@0" → getChunk(0) → Chunk object
  ↓
Chunk.__proto__.then → Chunk.prototype.then (actual function!)

Why this is critical:

  1. then resolves to Chunk.prototype.then - a real callable function
  2. This makes the fake object a valid thenable
  3. When awaited, JS calls obj.then(resolve, reject)
  4. Chunk.prototype.then executes with fake object as this:
Chunk.prototype.then = function (resolve, reject) {
  switch (this.status) {  // this.status = "resolved_model" ✓
    case "resolved_model":
      initializeModelChunk(this);  // fake object passed!
  1. initializeModelChunk(this) uses this._response - the attacker's fake _response:
value = reviveModel(
  chunk._response,  // ← attacker's fake _response!
  ...
);

Without the self-reference, the fake _response would never be used. The self-reference makes Chunk.prototype.then treat the attacker's object as a real Chunk.

Two-Stage Thenable Trigger (value)

The value field contains a nested JSON string with another thenable:

{"then":"$B1337"}

Stage 1: Outer object's self-referential then triggers chunk processing

Stage 2: When React resolves the model, it parses value and encounters another thenable with then: "$B1337". The $B prefix triggers the handler:

case "B":
  return response._formData.get(response._prefix + obj);  // obj = "1337"

_formData.get is "$1:constructor:constructor" → getOutlinedModel() resolves to Function.

This becomes: Function(code + "1337") → valid JS because 1337 is just a trailing expression.

Defensive Padding (_chunks)

The fake _response needs a valid _chunks property to prevent crashes:

Form field "2": []           ← empty array
_chunks: "$Q2"               ← $Q = Map type, creates new Map([])

React's internal code may access response._chunks.get() or response._chunks.has() during processing. An empty Map satisfies these calls without errors, allowing execution to reach the vulnerable $B handler.


Vulnerable Code Paths

PathFunctionPurpose in Exploit
Path TraversalgetOutlinedModel()Resolves $1:constructor:constructor → Function
Fake _response InjectioninitializeModelChunk()Uses attacker's chunk._response
$B HandlerparseModelString()Calls _formData.get(_prefix + id) → RCE

decodeReply() is the entry point, not vulnerable itself.

Path Traversal (getOutlinedModel()):

for (key = 1; key < reference.length; key++)
  parentObject = parentObject[reference[key]];  // No validation!

Fake Response Usage (initializeModelChunk()):

value = reviveModel(
  chunk._response,  // Uses chunk._response directly!
  { "": rawModel },
  ...
);

$B Handler RCE (parseModelString()):

case "B":
  return response._formData.get(response._prefix + obj);  // RCE!

The Fix (19.2.1)

The patch includes multiple fixes:

  1. RESPONSE_SYMBOL in initializeModelChunk() - Critical fix

    // BEFORE: chunk._response (attacker can set via JSON)
    value = reviveModel(chunk._response, ...);
    
    // AFTER: Symbol lookup (cannot be forged via JSON)
    var response = chunk.reason[RESPONSE_SYMBOL];
    value = reviveModel(response, ...);
    
  2. hasOwnProperty check in getOutlinedModel() - Blocks prototype traversal

    hasOwnProperty.call(value, name) && (value = value[name]);
    
  3. __proto__ handling in reviveModel() - Prevents prototype pollution

    void 0 !== parentObj || "__proto__" === i
      ? (value[i] = parentObj)
      : delete value[i];
    
  4. Type check in initializeModelChunk() - Validates listeners

    "function" === typeof listener
      ? listener(value)
      : fulfillReference(response, listener, value);
    

Impact & Versions

Impact Assessment

Download Tool