From 2c67cd595da212f959612d3c36d65152bd7a1dc7 Mon Sep 17 00:00:00 2001 From: kdletters Date: Fri, 19 Jun 2026 17:31:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E7=B4=A7=E7=A7=BB=E5=8A=A8=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E6=B3=A8=E5=85=A5=E8=BE=B9=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 要求 Expo 壳事件注入先校验共享 HostBridge 事件名 保留统一 message script 的 origin 和 source 约束 同步移动壳事件注入边界记录 --- apps/mobile-shell/scripts/check-config.mjs | 6 ++++++ apps/mobile-shell/src/shell/ShellApp.tsx | 21 +++++++++++++------ .../shared-memory/decision-log.md | 1 + 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index 541144390..f798010fe 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -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}`); diff --git a/apps/mobile-shell/src/shell/ShellApp.tsx b/apps/mobile-shell/src/shell/ShellApp.tsx index e35009e22..7f7160b80 100644 --- a/apps/mobile-shell/src/shell/ShellApp.tsx +++ b/apps/mobile-shell/src/shell/ShellApp.tsx @@ -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), ); }, [], diff --git a/docs/project-memory/shared-memory/decision-log.md b/docs/project-memory/shared-memory/decision-log.md index cf2ecd593..2aaacb857 100644 --- a/docs/project-memory/shared-memory/decision-log.md +++ b/docs/project-memory/shared-memory/decision-log.md @@ -2551,6 +2551,7 @@ - 背景:H5 主站会同时承载原生壳 HostBridge 和后续 AI H5 sandbox / GameBridge;如果 H5 侧只按 JSON envelope 识别 HostBridge response / event,sandbox 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`。