收口宿主壳外链打开协议
共享 HostBridge 契约新增外链 URL 协议白名单校验 Expo 移动壳打开外链前拒绝危险协议 Tauri 桌面壳打开外链前拒绝危险协议 补充共享契约、移动壳和桌面壳外链校验测试 更新宿主壳方案和团队共享决策记录
This commit is contained in:
@@ -87,6 +87,49 @@ export type OpenExternalUrlPayload = {
|
||||
url: string;
|
||||
};
|
||||
|
||||
export const HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS = [
|
||||
'http:',
|
||||
'https:',
|
||||
'mailto:',
|
||||
'tel:',
|
||||
] as const;
|
||||
|
||||
export type HostBridgeExternalUrlProtocol =
|
||||
(typeof HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS)[number];
|
||||
|
||||
function hasHostBridgeControlCharacter(value: string) {
|
||||
return [...value].some((character) => {
|
||||
const codePoint = character.codePointAt(0) ?? 0;
|
||||
return codePoint <= 31 || codePoint === 127;
|
||||
});
|
||||
}
|
||||
|
||||
export function normalizeHostBridgeExternalUrl(rawUrl: unknown) {
|
||||
if (typeof rawUrl !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const urlText = rawUrl.trim();
|
||||
if (!urlText || hasHostBridgeControlCharacter(urlText)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(urlText);
|
||||
if (
|
||||
!HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS.includes(
|
||||
url.protocol as HostBridgeExternalUrlProtocol,
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export type ClipboardWriteTextPayload = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user