Repository navigation
Conversation
Always register `addJavascriptInterface` on "ReactNativeWebView" as the
primary bridge, making `injectedObjectJson()` a native @JavascriptInterface
method available before DOMContentLoaded without JS aliasing.
When WML is supported, register it on an internal name
("__RNCWebViewMessageListener") and override `window.ReactNativeWebView`
with a wrapper (via Object.assign) that routes `postMessage` through WML
for origin security while preserving all other properties.
This eliminates the backtick injection vulnerability in the old
`injectJavascriptObject()` approach and provides a clearer mental model:
one bridge object, one optional messaging upgrade.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ntLoaded injection Use WebViewCompat.addDocumentStartJavaScript() API to inject injectedJavaScriptBeforeContentLoaded before any page content loads, replacing the unreliable evaluateJavascript() call during onPageStarted where the V8 context may not be ready. The document start script path activates when the DOCUMENT_START_SCRIPT feature is supported by the WebView. When mainFrameOnly is true (default), the script is wrapped with a top-frame guard. Falls back gracefully to the existing evaluateJavascript path on older WebViews. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82e8855 to
6e8ad60
Compare
|
mmm looks like the CI is failing potentially because iPhone 15 is old (?) but thanks @Kudo for working on this! it'd be great to get it in, would unlock a lot on my end :) |
|
Any updates here guys? |
# Why fixes dom components rendering problems on android (specific android 9) related to #34868 and #40413 close ENG-17714 # How - [dom] `injectedJavaScriptBeforeContentLoaded` is not reliable on android. use `injectedJavaScriptObject` instead. - [dom] inject `window.ReactNativeWebView.injectedObjectJson()` as `window.$$EXPO_INITIAL_PROPS` in entry html before going into bundle - [dom] entry html also adds polyfills for `globalThis` and `Array.flat` which android 9 factory webview doesn't support (chrome 66) - [metro-config][babel-preset-expo] for dom components, the babel should not use modern browser presets. > [!IMPORTANT] > because react-native-webview `injectedJavaScriptObject` is not reliable as well. i've created the pr to fix the problem react-native-webview/react-native-webview#3929. but we need to bump react-native-webview with the webview fix before merging the pr # Test Plan - apply changes from react-native-webview/react-native-webview#3929 - tested on android/ios on router-e2e dom components - tested on android 9 emulator # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [x] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why fixes dom components rendering problems on android (specific android 9) related to expo#34868 and expo#40413 close ENG-17714 # How - [dom] `injectedJavaScriptBeforeContentLoaded` is not reliable on android. use `injectedJavaScriptObject` instead. - [dom] inject `window.ReactNativeWebView.injectedObjectJson()` as `window.$$EXPO_INITIAL_PROPS` in entry html before going into bundle - [dom] entry html also adds polyfills for `globalThis` and `Array.flat` which android 9 factory webview doesn't support (chrome 66) - [metro-config][babel-preset-expo] for dom components, the babel should not use modern browser presets. > [!IMPORTANT] > because react-native-webview `injectedJavaScriptObject` is not reliable as well. i've created the pr to fix the problem react-native-webview/react-native-webview#3929. but we need to bump react-native-webview with the webview fix before merging the pr # Test Plan - apply changes from react-native-webview/react-native-webview#3929 - tested on android/ios on router-e2e dom components - tested on android 9 emulator # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [x] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
|
Is there any updates here? This fixes a code injection security issue so i think it should be prioritized |
|
Another downstream data point, since this PR fixes two bugs that turn out to be load-bearing simultaneously in the same code path. Context: Expo SDK 57 DOM components ( The Android symptom is a hard crash on mount: because What that costs downstream: two interlocking workarounds, one per bug this PR fixes.
That second one is the part worth flagging for prioritisation: it means the Happy to test this branch against a real Expo SDK 57 app with DOM components on Android and report back, if that would help move the review along. |
|
Downstream security impact evidence for this fix — executed on react-native-webview 13.16.0 (Android 15 emulator) Context: consumed by a production SDK ( Vulnerable sink on 13.16.0: Executed chain (all three stages, real device):
So the interpolation is not only an escape/robustness issue: any string that reaches Same-class sink on iOS in 13.16.0: Full logcat traces available if useful. |

Why
Fixing two issues on Android:
injectedJavaScriptBeforeContentLoadedon Android. This is a known issue as Code from the injectedJavaScriptBeforeContentLoaded prop runs AFTER the web code. #1609 and Add support for injectedJavaScriptBeforeContentLoaded on Android #1099.injectedJavaScriptObjectdoesn't work in some cases. fixes injectedJavaScriptObject prop (sometimes) does not work on Android #3326.How
injectedJavaScriptObject — Revamp bridge architecture
The old bridge architecture used
addWebMessageListener(WML) on"ReactNativeWebView"for messaging andaddJavascriptInterfaceon a separate name as fallback.injectedObjectJson()was injected viaevaluateJavascriptwith backtick interpolation, which was fragile and not running synchronously.The new design flips the relationship:
addJavascriptInterfaceis always registered on"ReactNativeWebView", makinginjectedObjectJson()a native@JavascriptInterfacemethod — available before DOMContentLoaded, no JS aliasing needed."__RNCWebViewMessageListener") for origin security.window.ReactNativeWebViewis replaced with a wrapper (viaObject.assign) that routespostMessagethrough WML while preserving all other properties includinginjectedObjectJson().injectedJavaScriptBeforeContentLoaded — Document Start Scripts
Use
WebViewCompat.addDocumentStartJavaScript()API to injectinjectedJavaScriptBeforeContentLoadedbefore any page content loads. This is similar toWKUserScriptInjectionTimeAtDocumentStarton iOS but only available in newer WebView (whenWebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)is available).For older Android WebView (e.g. factory Android 9 WebView), DSS is not supported and
injectedJavaScriptBeforeContentLoadedfalls back to the existingevaluateJavascriptpath (which remains unreliable on those devices — a known platform limitation).Test Plan
A new InjectedObjectJson example has been added to the example app to verify
injectedObjectJson()availability at both DOMContentLoaded and afterContentLoaded. Also verified the existing Messaging example to ensurepostMessagecontinues to work correctly.Modern Android (WML + DSS): Run the Injection and InjectedObjectJson examples
injectedObjectJson()should be available at both DOMContentLoaded and afterContentLoadedpostMessageshould work (messaging example)beforeContentLoadedinjection should succeed (injection example)Android 9 / old WebView (no WML, no DSS): Run same examples
injectedObjectJson()should work (RNCWebViewBridge, always available)postMessageshould work via@JavascriptInterfacebeforeContentLoadedmay be unreliable (known platform limitation)Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com