Get AI summaries of any video or article — Sign up free
How React took down Cloudflare thumbnail

How React took down Cloudflare

The PrimeTime·
5 min read

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.

TL;DR

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?

The transcript points to React 19’s “flight protocol,” where the server streams JSON instructions for the client to render. Those payloads can include unresolved promise placeholders, and React’s handling of its internal state for those placeholders can be manipulated. A crafted payload uses “model strings” (starting with “$”) to control how React resolves a promise at a given position, steering execution into a dangerous code path.

How does the exploit turn serialized data into executable code?

The key is a model string type labeled “B.” React decodes that type through a chain that reaches a thenable-like constructor and ultimately a form-data getter. The getter supplies a string built from a “responses prefix + an ID.” The payload is crafted so the resulting string is treated as code by the JavaScript Function constructor—using a trailing comment to prevent syntax errors—so attacker-controlled JavaScript runs.

Why did Cloudflare’s mitigation lead to an outage?

Cloudflare increased an HTTP buffer size from 128 KB to 1 MB as part of mitigation while RCE traffic spiked. The transcript says this change didn’t break normal behavior, but it caused an internal testing tool to fail because it couldn’t handle the larger buffer. Disabling that tool then broke the Lua front line’s “execute” rule-set flow.

What specifically failed inside the Lua front line?

Requests tagged with an “execute” action expected additional rule-set results. With the internal testing behavior disrupted, those extra results were missing and came back as nil. Lua’s lack of the same safety guarantees meant the logic then crashed when it tried to use the nonexistent rule-set output.

Why didn’t the Rust-based component crash the same way?

The transcript attributes the difference to Rust’s safety model: it prevents certain classes of runtime errors (described as avoiding “pain” by catching issues earlier). As a result, the Rust front line (FL2) remained safe even after the mitigation changes that destabilized the Lua front line (FL1).

What broader historical warning does the transcript connect to this issue?

It cites a 1994 paper warning that treating server and client as the same machine—so objects can be interpreted across boundaries without strict separation—can produce disastrous operations and require “voodoo” workarounds. The transcript also claims Java already had this problem, framing the React issue as part of a long-known serialization/execution boundary risk.

Review Questions

  1. How does the flight protocol’s promise-handling interact with crafted model strings to reach the Function constructor?
  2. Describe the chain of events from Cloudflare’s HTTP buffer change to the Lua front line crash, including what “nil” represented in the failure.
  3. 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. 1

    React 19’s flight protocol can be abused via a serialization/deserialization flaw to trigger remote code execution without authentication.

  2. 2

    The exploit uses streamed “model strings” (prefixed with “$”) and a special model type (“B”) to route execution toward JavaScript’s Function constructor.

  3. 3

    A successful payload can be shaped to read environment variables and exfiltrate them, making the impact severe even without login.

  4. 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. 5

    The Lua-based front line crashed when “execute” actions expected rule-set results that became nil after the mitigation disruption.

  6. 6

    The Rust-based front line avoided the crash, underscoring how language/runtime safety can change failure modes during incident response.

Highlights

The RCE mechanism is traced to React’s flight protocol: crafted payloads steer React into invoking the Function constructor through a model-string decoding path.
Cloudflare’s outage is portrayed as a mitigation side effect: buffer-size changes destabilized an internal testing tool, which then caused a Lua front line to crash.
The transcript contrasts Lua and Rust failure behavior, crediting Rust’s safety model for preventing the same crash pattern.
A historical 1994 warning is cited: blurring server/client execution boundaries can lead to “voodoo” workarounds and disastrous outcomes—an issue echoed in modern serialization attacks.

Topics

  • React Flight Protocol
  • Remote Code Execution
  • Serialization Vulnerability
  • Cloudflare Mitigation
  • Lua vs Rust Safety

Mentioned