收紧移动事件注入边界

要求 Expo 壳事件注入先校验共享 HostBridge 事件名

保留统一 message script 的 origin 和 source 约束

同步移动壳事件注入边界记录
This commit is contained in:
2026-06-19 17:31:48 +08:00
parent 2709f48118
commit 2c67cd595d
3 changed files with 22 additions and 6 deletions
@@ -1110,7 +1110,13 @@ for (const snippet of [
for (const snippet of [
'type HostBridgeEventName',
'isHostBridgeEventName',
'function buildHostBridgeEventScript(event: HostBridgeEventName, payload: unknown)',
'if (!isHostBridgeEventName(event))',
'throw new Error(`unsupported HostBridge event ${event}`)',
'return buildHostBridgeMessageScript({',
'(event: HostBridgeEventName, payload: unknown)',
'buildHostBridgeEventScript(event, payload)',
]) {
if (!shellAppSource.includes(snippet)) {
throw new Error(`mobile shell HostBridge event injection missing ${snippet}`);
+15 -6
View File
@@ -19,6 +19,7 @@ import {
type HostBridgeEventName,
HOST_BRIDGE_PROTOCOL,
HOST_BRIDGE_VERSION,
isHostBridgeEventName,
} from '../../../../packages/shared/src/contracts/hostBridge';
import {
configureMobileHostBridgeNavigation,
@@ -59,6 +60,19 @@ function buildHostBridgeMessageScript(message: unknown) {
)}, origin: window.location.origin, source: window })); true;`;
}
function buildHostBridgeEventScript(event: HostBridgeEventName, payload: unknown) {
if (!isHostBridgeEventName(event)) {
throw new Error(`unsupported HostBridge event ${event}`);
}
return buildHostBridgeMessageScript({
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
event,
payload,
});
}
type MobileWebViewLoadErrorEvent = {
nativeEvent: {
url: string;
@@ -103,12 +117,7 @@ export default function ShellApp() {
const injectHostBridgeEvent = useCallback(
(event: HostBridgeEventName, payload: unknown) => {
webViewRef.current?.injectJavaScript(
buildHostBridgeMessageScript({
bridge: HOST_BRIDGE_PROTOCOL,
version: HOST_BRIDGE_VERSION,
event,
payload,
}),
buildHostBridgeEventScript(event, payload),
);
},
[],
@@ -2551,6 +2551,7 @@
- 背景:H5 主站会同时承载原生壳 HostBridge 和后续 AI H5 sandbox / GameBridge;如果 H5 侧只按 JSON envelope 识别 HostBridge response / eventsandbox iframe 可以构造同形 `postMessage` 干扰待处理宿主请求或伪造宿主事件。
- 决策:Expo 和 Tauri 注入给 H5 的 HostBridge response / event 统一带 `origin: window.location.origin``source: window``nativeAppHostBridge` listener 只接受无外部 source 或当前窗口 source 的消息,并拒绝非当前页面 origin。AI sandbox 后续继续使用独立 GameBridge allowlist,不允许直接结算 HostBridge 请求。
- 追加:Expo 移动壳事件注入必须在运行时调用共享 `isHostBridgeEventName()` 校验事件名,只有 `HOST_BRIDGE_EVENTS` 中的事件才能生成注入脚本;普通 response 仍可复用统一 message script,但不能绕过事件 allowlist 伪造新的宿主事件类型。`apps/mobile-shell/scripts/check-config.mjs` 必须反查该校验。
- 影响范围:`apps/mobile-shell/App.tsx``apps/desktop-shell/src-tauri/src/main.rs``src/services/host-bridge/nativeAppHostBridge.ts`、两端壳配置检查和 HostBridge 方案文档。
- 验证方式:`npm run check:native-shells``npm run test -- src/services/host-bridge/nativeAppHostBridge.test.ts src/services/host-bridge/hostBridge.test.ts``npm run typecheck``npm run check:encoding``git diff --check`