收紧移动事件注入边界
要求 Expo 壳事件注入先校验共享 HostBridge 事件名 保留统一 message script 的 origin 和 source 约束 同步移动壳事件注入边界记录
This commit is contained in:
@@ -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}`);
|
||||
|
||||
@@ -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 / 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`。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user