收紧移动壳外链协议白名单

Expo WebView 外域导航只允许安全外链协议交给系统

阻断危险协议避免外链页面保留宿主桥能力

补充移动壳导航测试和宿主壳文档
This commit is contained in:
2026-06-18 00:35:14 +08:00
parent fec8b626f5
commit ee49c26868
5 changed files with 33 additions and 4 deletions

View File

@@ -10,7 +10,10 @@ import {
MOBILE_HOST_CAPABILITIES,
} from './src/mobileHostBridge';
import { buildMobileShellUrlFromDeepLink } from './src/mobileShellDeepLink';
import { shouldOpenInMobileShellWebView } from './src/mobileShellNavigation';
import {
resolveMobileShellExternalUrl,
shouldOpenInMobileShellWebView,
} from './src/mobileShellNavigation';
import { buildMobileShellUrl } from './src/mobileShellUrl';
const defaultWebUrl = 'http://127.0.0.1:3000/';
@@ -107,7 +110,10 @@ export default function App() {
return true;
}
void Linking.openURL(request.url).catch(() => undefined);
const externalUrl = resolveMobileShellExternalUrl(request.url);
if (externalUrl) {
void Linking.openURL(externalUrl).catch(() => undefined);
}
return false;
};

View File

@@ -1,6 +1,7 @@
import { describe, expect, test } from 'vitest';
import {
resolveMobileShellExternalUrl,
resolveMobileShellWebViewUrl,
shouldOpenInMobileShellWebView,
} from './mobileShellNavigation';
@@ -37,6 +38,21 @@ describe('shouldOpenInMobileShellWebView', () => {
);
});
test('只有允许协议能交给系统外部应用打开', () => {
expect(resolveMobileShellExternalUrl(' https://example.com/path ')).toBe(
'https://example.com/path',
);
expect(resolveMobileShellExternalUrl('mailto:hi@example.com')).toBe(
'mailto:hi@example.com',
);
expect(resolveMobileShellExternalUrl('tel:+12345678')).toBe(
'tel:+12345678',
);
expect(resolveMobileShellExternalUrl('javascript:alert(1)')).toBeNull();
expect(resolveMobileShellExternalUrl('file:///etc/passwd')).toBeNull();
expect(resolveMobileShellExternalUrl('/relative/path')).toBeNull();
});
test('HostBridge 主动导航只解析同源网页目标', () => {
const allowedOrigin = 'https://app.genarrative.world';

View File

@@ -1,3 +1,5 @@
import { normalizeHostBridgeExternalUrl } from '../../../packages/shared/src/contracts/hostBridge';
export function shouldOpenInMobileShellWebView(
rawUrl: string,
allowedOrigin: string,
@@ -26,6 +28,10 @@ export function shouldOpenInMobileShellWebView(
}
}
export function resolveMobileShellExternalUrl(rawUrl: string) {
return normalizeHostBridgeExternalUrl(rawUrl);
}
export function resolveMobileShellWebViewUrl(
rawUrl: string,
allowedOrigin: string,