DEV Community

Cover image for CVE-2025-55182: How React’s Biggest Vulnerability Happened — and What It Teaches Us About Modern Web Security
Vo Thanh Dat
Vo Thanh Dat

Posted on

CVE-2025-55182: How React’s Biggest Vulnerability Happened — and What It Teaches Us About Modern Web Security

CVE-2025-55182 was one of the most impactful vulnerabilities ever discovered in the React ecosystem.

It enabled remote code execution (RCE) through React Server Components (RSC), affecting any framework that exposed RSC endpoints (including Next.js).

This write-up is the result of a deep technical exploration driven by my own curiosity, studied and refined through multiple detailed discussions with ChatGPT. The goal is to summarize why this class of flaw happens and how engineers can prevent it in the future.


1. The Root Issue: An Internal Protocol Became Public

React Server Components rely on a custom binary protocol (“React Flight”).

It supports:

  • function references
  • streaming
  • partial payloads
  • nested structures
  • typed opcodes

Originally, this protocol was intended for internal use only.

But when frameworks adopted RSC, the endpoints became publicly accessible:

/react
/_rsc
/_next/data/.../flight
Enter fullscreen mode Exit fullscreen mode

This created an unexpected trust boundary:

A private serialization format suddenly became an internet-facing attack surface.

Once exposed, attackers could craft and send custom binary payloads directly.


2. The Vulnerability: Unsafe Deserialization

React’s server decoder accepted untrusted data and reconstructed complex JavaScript objects from it.

This included dangerous shapes such as:

  • objects with __proto__
  • objects with constructor
  • unexpected nested structures
  • dynamic function references

Malformed payloads could manipulate object shapes in ways React never intended—eventually triggering execution of attacker-controlled code.

This was not a one-line bug.

It was an architectural issue: a powerful decoder without strict validation.


3. Why This Still Happens Even on Senior Teams

3.1. Tools don’t catch architectural vulnerabilities

LLMs and static analysis tools identify code-level problems, not:

  • cross-layer trust boundaries
  • binary protocol semantics
  • implicit assumptions in distributed systems
  • malformed deserialization paths

These issues require threat modeling, not linting.


3.2. Assumption Drift During Framework Evolution

Initial assumption:

“Only React’s client will send these payloads.”

Deployment reality:

“Anyone on the internet can send anything.”

When architecture evolves, assumptions silently break.


3.3. Complexity Increases Attack Surface

RSC’s protocol is complex:

  • streaming
  • references
  • type tags
  • custom opcodes

More flexibility = more ways to break validation.


3.4. Security is a Specialized Discipline

React engineers are experts in rendering, scheduling, and compilers.

Security engineering requires:

  • adversarial thinking
  • fuzzing
  • protocol mutation testing
  • zero-trust data pipelines

General engineering excellence does not automatically cover protocol security.


4. How React Fixed It

  • Strict schema validation

    Only JSON-safe primitives are allowed:

    • strings
    • numbers
    • booleans
    • arrays
    • plain objects
    • no prototypes
  • Dangerous keys are banned

Payloads are rejected if they contain:

  • __proto__
  • constructor
  • prototype

    • Static server action manifest

Server actions must be known at build time.

  • Hardened Next.js endpoints

Includes:

  • stricter MIME types
  • body size limits
  • narrower set of exposed routes

    • Extensive fuzzing

The Flight protocol decoder is now actively fuzz-tested against malformed input.

React essentially turned a flexible binary decoder into a strict zero-trust protocol.


5. Key Lessons for Engineers

  • Never deserialize untrusted input into complex objects: Restrict input to validated, primitive data.

  • Document and enforce trust boundaries : Every public endpoint is hostile by default.

  • Add fuzz testing for protocols : Unusual input is the first thing attackers will try.

  • Be careful with “internal-only” protocols : Anything shipped in production becomes public—eventually someone will target it.

  • Security requires dedicated review : Complex systems need added adversarial analysis.


Conclusion

CVE-2025-55182 demonstrates how architectural assumptions can silently turn into vulnerabilities, even inside highly sophisticated frameworks maintained by world-class engineers.

This article captures insights gained through a deep technical investigation and iterative discussions with ChatGPT. The core lesson is universal:

Never assume your protocol will only be used the way you expect.

Expose it to the internet, and it becomes an attack vector.

Security must be designed from the ground up—especially when serialization, deserialization, and trust boundaries meet.

Top comments (0)