Deserialization/Thenable handling

MEDIUM
facebook/react
Commit: 3016ff87d87a
Affected: 19.2.0 - 19.2.3
2026-04-03 23:59 UTC

Description

The commit adds guards in React Flight server code to ignore keys named 'then' when processing server references and model creation during Flight reply serialization/deserialization. Specifically, loadServerReference returns null if key === 'then', and createModel returns null if the key is 'then' and the value is a function. This mitigates potential deserialization/thenable abuse where a crafted payload containing a 'then' property could be misinterpreted as a promise/thenable, leading to unintended behavior or security risk. The fix prevents treating such keys/functions as valid flight payload data and instead nulls them, reducing exposure to promise-related abuse during Flight data handling.

Commit Details

Author: Sebastian Markbåge

Date: 2025-12-05 00:05 UTC

Message:

[Flight] Never parse "then" functions (#35289) AFAIK this is not needed to prevent any exploit but we don't really need this. We allow functions on pretty much any other object anyway but never on the "then" property since those would be serialized as Promises by the client anyway.

Triage Assessment

Vulnerability Type: Deserialization/Thenable handling

Confidence: MEDIUM

Reasoning:

The commit adds guards to prevent handling of objects with a then property (specifically when serializing/deserializing flight data). By returning null for then-bearing keys and then functions, it mitigates potential abuse via crafted payloads that could exploit thenables during deserialization/serialization. This is a defensive security measure related to deserialization/thenable handling rather than a pure bug fix or feature.

Verification Assessment

Vulnerability Type: Deserialization/Thenable handling

Confidence: MEDIUM

Affected Versions: 19.2.0 - 19.2.3

Code Diff

diff --git a/packages/react-server/src/ReactFlightReplyServer.js b/packages/react-server/src/ReactFlightReplyServer.js index 39734dae7ca2..742cae6d2012 100644 --- a/packages/react-server/src/ReactFlightReplyServer.js +++ b/packages/react-server/src/ReactFlightReplyServer.js @@ -437,6 +437,11 @@ function loadServerReference<A: Iterable<any>, T>( if (typeof id !== 'string') { return (null: any); } + if (key === 'then') { + // This should never happen because we always serialize objects with then-functions + // as "thenable" which reduces to ReactPromise with no other fields. + return (null: any); + } const serverReference: ServerReference<T> = resolveServerReference<$FlowFixMe>(response._bundlerConfig, id); // We expect most servers to not really need this because you'd just have all @@ -976,7 +981,17 @@ function extractIterator(response: Response, model: Array<any>): Iterator<any> { return model[Symbol.iterator](); } -function createModel(response: Response, model: any): any { +function createModel( + response: Response, + model: any, + parentObject: Object, + key: string, +): any { + if (key === 'then' && typeof model === 'function') { + // This should never happen because we always serialize objects with then-functions + // as "thenable" which reduces to ReactPromise with no other fields. + return null; + } return model; }
← Back to Alerts View on GitHub →