Information Disclosure
Description
The commit changes production error handling for all browser bundles to minify prod error codes/messages, reducing information leakage. It also expands the error code map (scripts/error-codes/codes.json) and flips minifyWithProdErrorCodes from false to true for multiple bundles. The resulting behavior is that production browser errors no longer expose verbose internal messages or stack traces, mitigating potential information disclosure about internal server/client boundaries and bundler details.
Proof of Concept
PoC (conceptual): In a production build of a React app prior to this fix (e.g., 19.2.3), trigger a runtime error that originates from the server/client boundary (such as rendering a Server Component or invoking a server action). The browser console or error overlay may reveal verbose internal messages (module paths, server/client boundary notes, bundler details). After upgrading to 19.2.4 (where minifyWithProdErrorCodes is enabled for browser bundles), the same error would be sanitized to a generic message or code, with no exposed internal details. Example trigger (conceptual):
- Server-side component throws new Error("Cannot find module \"../internal/secret\" in React Server Components");
- Client observes a production error in the console that lacks internal paths or sensitive details and shows only a sanitized error code/message.
Note: This PoC is conceptual and assumes a server components setup in production. Actual reproduction requires a controlled environment with a pre-fix production build (19.2.3) and the post-fix build (19.2.4) for comparison.
Commit Details
Author: Sebastian "Sebbie" Silbermann
Date: 2026-04-17 16:01 UTC
Message:
Minify prod error messages for all browser bundles (#36277)
Triage Assessment
Vulnerability Type: Information Disclosure
Confidence: MEDIUM
Reasoning:
The change switches prod error messages to be minified in browser bundles, reducing the amount of potentially sensitive internal error details exposed to clients. This aligns with reducing information disclosure risk (information leakage) in production.
Verification Assessment
Vulnerability Type: Information Disclosure
Confidence: MEDIUM
Affected Versions: Pre-19.2.4; specifically 19.2.0 through 19.2.3 (inclusive) for browser bundles; fixed in 19.2.4.
Code Diff
diff --git a/scripts/error-codes/codes.json b/scripts/error-codes/codes.json
index db92efc075c..345aa2b0aaf 100644
--- a/scripts/error-codes/codes.json
+++ b/scripts/error-codes/codes.json
@@ -568,5 +568,19 @@
"580": "Server Function has too many bound arguments. Received %s but the limit is %s.",
"581": "BigInt is too large. Received %s digits but the limit is %s.",
"582": "Referenced Blob is not a Blob.",
- "583": "The current renderer does not support view transitions. This error is likely caused by a bug in React. Please file an issue."
-}
+ "583": "The current renderer does not support view transitions. This error is likely caused by a bug in React. Please file an issue.",
+ "584": "Attempted to load a Server Reference outside the hosted root.",
+ "585": "Invalid server action: %s",
+ "586": "No server callback has been registered. Call setServerCallback to register one.",
+ "587": "Server actions must be functions",
+ "588": "Could not find the module \"%s\" in the React Server Consumer Manifest. This is probably a bug in the React Server Components bundler.",
+ "589": "Could not find the module \"%s\" in the React Server Manifest. This is probably a bug in the React Server Components bundler.",
+ "590": "Cannot await or return from a thenable. You cannot await a client module from a server component.",
+ "591": "Cannot access %s on the server. You cannot dot into a client module from a server component. You can only pass the imported name through.",
+ "592": "Cannot assign to a client module from a server module.",
+ "593": "Attempted to call the default export of %s from the server but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.",
+ "594": "Cannot read Symbol exports. Only named exports are supported on a client module imported on the server.",
+ "595": "Attempted to call %s() from the server but %s is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.",
+ "596": "Could not find the module \"%s\" in the React Client Manifest. This is probably a bug in the React Server Components bundler.",
+ "597": "The module \"%s\" is marked as an async ESM module but was loaded as a CJS proxy. This is probably a bug in the React Server Components bundler."
+}
\ No newline at end of file
diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js
index 7b9508b9e29..25e5f31bf9e 100644
--- a/scripts/rollup/bundles.js
+++ b/scripts/rollup/bundles.js
@@ -415,7 +415,7 @@ const bundles = [
entry: 'react-dom/unstable_server-external-runtime',
outputPath: 'unstable_server-external-runtime.js',
global: 'ReactDOMServerExternalRuntime',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: [],
},
@@ -454,7 +454,7 @@ const bundles = [
name: 'react-server-dom-webpack-server.browser',
condition: 'react-server',
global: 'ReactServerDOMServer',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -496,7 +496,7 @@ const bundles = [
'react-server-dom-webpack/src/client/react-flight-dom-client.browser',
name: 'react-server-dom-webpack-client.browser',
global: 'ReactServerDOMClient',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -566,7 +566,7 @@ const bundles = [
name: 'react-server-dom-turbopack-server.browser',
condition: 'react-server',
global: 'ReactServerDOMServer',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -608,7 +608,7 @@ const bundles = [
'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',
name: 'react-server-dom-turbopack-client.browser',
global: 'ReactServerDOMClient',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -641,7 +641,7 @@ const bundles = [
name: 'react-server-dom-parcel-server.browser',
condition: 'react-server',
global: 'ReactServerDOMServer',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -682,7 +682,7 @@ const bundles = [
entry: 'react-server-dom-parcel/src/client/react-flight-dom-client.browser',
name: 'react-server-dom-parcel-client.browser',
global: 'ReactServerDOMClient',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},
@@ -731,7 +731,7 @@ const bundles = [
bundleTypes: [NODE_DEV, NODE_PROD, ESM_DEV, ESM_PROD],
moduleType: RENDERER,
entry: 'react-server-dom-esm/client.browser',
- minifyWithProdErrorCodes: false,
+ minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react', 'react-dom'],
},