Hi everyone
In a recent, I examined CVE-2025-55182, a critical vulnerability in React Server Components caused by an unsafe deserialization path that could lead to unauthenticated remote code execution. That issue highlighted how deeply framework internals can influence the security posture of applications built on top of them.
Shortly after that disclosure, an additional set of security vulnerabilities was published affecting the same architectural layer in React Server Components (RSC) and Next.js. While these issues do not result in immediate remote code execution, they introduce significant risks, including Denial of Service (DoS) and unintended exposure of server-side source code and internal implementation details under specific conditions.
This article builds on that context and focuses on the underlying execution model of React Server Components, explaining how these issues emerge at the framework level and why they matter for production deployments.
To understand why the recently disclosed issues in React Server Components (RSC) lead to Denial of Service and source code exposure, it helps to look at how the RSC execution pipeline actually works on the server.
React Server Components: Server-Side Execution Flow
A simplified but accurate RSC request lifecycle looks like this:
1 - Incoming request reaches the RSC endpoint
- In Next.js, this typically maps to an internal route such as /_rsc
- The request is processed before authentication and before application middleware
2 - Request body parsing and protocol decoding
- The payload is parsed according to the React Flight protocol
- This includes decoding serialized component references, props, and execution hints
- At this stage, React assumes the payload shape is valid enough to be processed
3 - Component graph reconstruction
- React reconstructs the Server Component tree from the serialized input
- Module references are resolved and loaded
- Async boundaries and Suspense segments are registered
4 - Server rendering and streaming
- Components are executed on the server
- Output is serialized again and streamed back to the client in chunks
- Error boundaries and partial results are flushed incrementally
5 - Error and recovery
- If an exception occurs mid-stream, React attempts to recover gracefully
- Metadata, stack traces, and module identifiers are still available internally
- Each of these phases is sensitive to malformed or adversarial input.
How Denial of Service Is Triggered
The DoS issue arises primarily in steps 2 and 3, before any application logic is involved.
A malicious request can:
- Inflate the serialized payload size
- Introduce deeply nested or cyclic references
- Force excessive async boundary resolution
Conceptual example:
POST /_rsc
Content-Type: application/json
{
"type": "ServerComponent",
"props": {
"children": {
"children": {
"children": {
...
}
}
}
}
}
Even if the payload is syntactically valid, React will:
- Attempt to deserialize it
- Build an in-memory component graph
- Schedule execution and streaming work
This leads to:
- High CPU usage during decoding
- Memory pressure during graph reconstruction
- Worker or event-loop saturation
Crucially, this happens without hitting user-defined code and without authentication.
This makes traditional defensive assumptions at the application layer largely ineffective.
How Source Code Exposure Can Occur
Source code exposure is a side effect of how React handles errors during steps 4 and 5.
When a rendering or serialization error occurs mid-stream:
- React still holds references to internal module paths
- Stack traces include resolved file locations
- Component metadata is partially serialized
In certain edge cases, this information may:
- Leak into the streamed response
- Appear in error payloads
- Be flushed before the stream is properly aborted
Example of leaked information:
Error: Failed to resolve Server Component
at /app/src/components/admin/UserList.server.tsx
at react-server-dom-webpack/server
This reveals:
- Project directory structure
- Server-only component boundaries
- Internal module layout and naming
While not a standalone exploit, this materially reduces the effort required for targeted attacks.
Why Server Actions Are Not Required
A common misconception is that these risks only apply when using Server Actions.
In reality:
- Server Actions are an API surface
- RSC is a runtime and protocol
Even a simple page like:
export default async function Page() {
return <Dashboard />;
}
Still triggers:
- Request deserialization
- Component graph reconstruction
- Server execution and streaming
The vulnerable logic executes regardless of whether Server Actions are defined.
Key Takeaways
- React Server Components introduce a fundamentally new server-side execution model that combines request deserialization, component graph reconstruction, and streaming-based rendering into a single framework-managed pipeline.
- As a result, the effective attack surface exists before authentication, before application middleware, and before any user-defined business logic is executed.
- Malformed or adversarial RSC requests can lead to:
- Denial of Service, through excessive CPU usage, memory pressure, and worker or event-loop saturation during deserialization and component graph reconstruction
- Accidental disclosure of server-side implementation details, including internal file paths, component boundaries, and module layout, as a side effect of streaming error handling
- These issues are not caused by misconfigured applications or unsafe user code. They are framework-level vulnerabilities in the React Server Components runtime itself and cannot be mitigated reliably through application-layer defenses alone.
Official advisories and patches
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.