How React took down Cloudflare
Based on The PrimeTime's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
React 19’s flight protocol can be abused via a serialization/deserialization flaw to trigger remote code execution without authentication.
Briefing
A React vulnerability tied to a serialization/deserialization flaw enabled remote code execution without authentication—letting an attacker read a server’s environment variables and exfiltrate them. The core mechanism hinges on React’s “flight protocol” payloads, where the server can stream instructions for the client to render. In React 19, those streamed JSON payloads can include unresolved promise placeholders, and the client’s internal state handling can be manipulated so that React ends up invoking JavaScript’s Function constructor via a crafted “model string” path.
The transcript walks through a minimal reproduction built from two streamed chunks (labeled 0 and 1). Within the payload, “model strings” begin with a dollar sign and instruct React to resolve a promise at a specific position. The critical piece is a model string type labeled “B,” which React decodes through a chain that ultimately reaches a thenable-like constructor. That decoding path routes through a form-data style getter, and the getter supplies a “responses prefix + an ID” value. The payload is arranged so that the resulting string becomes code—wrapped with a comment terminator to avoid syntax errors—so the Function constructor executes attacker-controlled JavaScript.
Cloudflare’s connection to the incident came from mitigation steps taken while responding to the widespread RCE. As traffic surged with React-triggered 500 errors, Cloudflare adjusted an HTTP buffer size—raising the default from 128 KB up to 1 MB, reportedly aligned with guidance associated with Next.js. That change itself appeared to behave normally for most traffic, but it broke an internal testing tool that Cloudflare had in place. The mitigation effectively disabled or destabilized the tool, and that tool’s failure cascaded into a front-line component written in Lua.
In the Lua-based front line (referred to as FL1), requests tagged with an “execute” action expected additional rule-set results. With the internal testing behavior turned off or malfunctioning, those extra results came back as nil. The Lua logic then attempted to use the missing rule-set output, causing the system to crash—an outage that the transcript attributes to a nil dereference-style failure. The upgraded front line written in Rust (FL2) did not suffer the same fate, with the transcript crediting Rust’s safety model for preventing the crash.
The scale of the disruption is described as roughly 22 to 25 million requests per second impacted—enough to affect a meaningful slice of the internet. The broader lesson is that serialization bugs can be extraordinarily hard to contain: even when the original vulnerability is in a widely used library like React, infrastructure mitigations can trigger unexpected failures in adjacent systems.
The transcript also notes that Java has long had similar pitfalls, citing a 1994 paper warning that treating server and client as the same execution context can lead to disastrous outcomes. A final shout-out credits “Lackland Davidson” with 100+ hours of work uncovering the vulnerability, implying the discovery helped prevent a long-lived, potentially permanent class of exploitation.
Cornell Notes
React 19’s flight protocol can be abused through a serialization/deserialization flaw to achieve remote code execution without authentication. The exploit relies on crafted “model strings” in streamed payloads, where an unresolved promise and a special model type (“B”) steer React into using JavaScript’s Function constructor. That execution path can be shaped to read environment variables and exfiltrate them. Cloudflare’s attempt to mitigate the surge—by changing an HTTP buffer size—accidentally broke an internal testing tool, which then caused a Lua-based front line to crash when “execute” actions expected rule-set results that became nil. A Rust-based front line avoided the crash, highlighting how language/runtime safety can change failure modes.
What part of React’s architecture makes this RCE possible?
How does the exploit turn serialized data into executable code?
Why did Cloudflare’s mitigation lead to an outage?
What specifically failed inside the Lua front line?
Why didn’t the Rust-based component crash the same way?
What broader historical warning does the transcript connect to this issue?
Review Questions
- How does the flight protocol’s promise-handling interact with crafted model strings to reach the Function constructor?
- Describe the chain of events from Cloudflare’s HTTP buffer change to the Lua front line crash, including what “nil” represented in the failure.
- What engineering lesson does the transcript draw from the difference between the Lua front line (FL1) and the Rust front line (FL2)?
Key Points
- 1
React 19’s flight protocol can be abused via a serialization/deserialization flaw to trigger remote code execution without authentication.
- 2
The exploit uses streamed “model strings” (prefixed with “$”) and a special model type (“B”) to route execution toward JavaScript’s Function constructor.
- 3
A successful payload can be shaped to read environment variables and exfiltrate them, making the impact severe even without login.
- 4
Cloudflare’s mitigation—raising an HTTP buffer size from 128 KB to 1 MB—broke an internal testing tool that couldn’t handle the new size.
- 5
The Lua-based front line crashed when “execute” actions expected rule-set results that became nil after the mitigation disruption.
- 6
The Rust-based front line avoided the crash, underscoring how language/runtime safety can change failure modes during incident response.