收口宿主壳外链打开协议
共享 HostBridge 契约新增外链 URL 协议白名单校验 Expo 移动壳打开外链前拒绝危险协议 Tauri 桌面壳打开外链前拒绝危险协议 补充共享契约、移动壳和桌面壳外链校验测试 更新宿主壳方案和团队共享决策记录
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import * as Linking from 'expo-linking';
|
||||
import { afterEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
@@ -83,6 +84,7 @@ function expectFailed(response: HostBridgeResponse) {
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
vi.mocked(Linking.openURL).mockReset();
|
||||
configureMobileHostBridgeNavigation(null);
|
||||
});
|
||||
|
||||
@@ -148,4 +150,28 @@ describe('handleMobileHostBridgeMessage', () => {
|
||||
|
||||
expect(failedResponse.error.code).toBe('unsupported_method');
|
||||
});
|
||||
|
||||
test('app.openExternalUrl 只打开允许的外链协议', async () => {
|
||||
const response = await send(
|
||||
request('app.openExternalUrl', {
|
||||
url: ' https://example.com/path ',
|
||||
}),
|
||||
);
|
||||
|
||||
expectOk(response);
|
||||
expect(Linking.openURL).toHaveBeenCalledWith('https://example.com/path');
|
||||
});
|
||||
|
||||
test('app.openExternalUrl 拒绝危险协议', async () => {
|
||||
const response = await send(
|
||||
request('app.openExternalUrl', {
|
||||
url: 'javascript:alert(1)',
|
||||
}),
|
||||
);
|
||||
|
||||
const failedResponse = expectFailed(response);
|
||||
|
||||
expect(failedResponse.error.code).toBe('invalid_request');
|
||||
expect(Linking.openURL).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
type HostBridgeRequest,
|
||||
type HostBridgeResponse,
|
||||
type NavigateNativePagePayload,
|
||||
normalizeHostBridgeExternalUrl,
|
||||
type OpenExternalUrlPayload,
|
||||
type ShareOpenPayload,
|
||||
} from '../../../packages/shared/src/contracts/hostBridge';
|
||||
@@ -106,9 +107,11 @@ function failure(
|
||||
}
|
||||
|
||||
async function openExternalUrl(payload: unknown) {
|
||||
const url = (payload as OpenExternalUrlPayload | undefined)?.url;
|
||||
const url = normalizeHostBridgeExternalUrl(
|
||||
(payload as OpenExternalUrlPayload | undefined)?.url,
|
||||
);
|
||||
if (!url) {
|
||||
throw invalidRequest('url is required');
|
||||
throw invalidRequest('url must use an allowed external protocol');
|
||||
}
|
||||
|
||||
await Linking.openURL(url);
|
||||
|
||||
Reference in New Issue
Block a user