diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs
index 4bca38ea6..47e8717b4 100644
--- a/apps/mobile-shell/scripts/check-config.mjs
+++ b/apps/mobile-shell/scripts/check-config.mjs
@@ -1503,6 +1503,7 @@ for (const snippet of [
'SafeAreaView',
'MOBILE_SHELL_SAFE_AREA_EDGES',
'resolveMobileShellBaseWebUrl',
+ 'originWhitelist={[allowedWebOrigin]}',
'javaScriptCanOpenWindowsAutomatically={false}',
'mixedContentMode="never"',
'allowFileAccess={false}',
@@ -1537,6 +1538,10 @@ if (!shellAppTestSource.includes('blocked WebView file downloads are logged for
throw new Error('mobile shell tests must cover blocked WebView file download diagnostics');
}
+if (!shellAppTestSource.includes('WebView origin whitelist is limited to the resolved H5 origin')) {
+ throw new Error('mobile shell tests must cover WebView origin whitelist boundaries');
+}
+
for (const snippet of [
"describe('mobile shell safe area'",
"test('protects the WebView from every device edge'",
diff --git a/apps/mobile-shell/src/shell/ShellApp.test.tsx b/apps/mobile-shell/src/shell/ShellApp.test.tsx
index 5596908d4..5bf318e10 100644
--- a/apps/mobile-shell/src/shell/ShellApp.test.tsx
+++ b/apps/mobile-shell/src/shell/ShellApp.test.tsx
@@ -440,6 +440,19 @@ describe('ShellApp QR scanner HostBridge flow', () => {
});
describe('ShellApp HostBridge event injection', () => {
+ test('WebView origin whitelist is limited to the resolved H5 origin', async () => {
+ const ShellApp = await importShellApp();
+ render();
+
+ const webViewProps = shellHarness.webViewProps.current as {
+ originWhitelist?: string[];
+ source?: { uri?: string };
+ };
+ const webViewUrl = webViewProps.source?.uri ?? 'https://app.genarrative.world/';
+
+ expect(webViewProps.originWhitelist).toEqual([new URL(webViewUrl).origin]);
+ });
+
test('AppState changes inject app.lifecycle events into WebView', async () => {
const ShellApp = await importShellApp();
render();