收紧桌面命令权限产物门禁
要求 Tauri 自动生成权限目录必须存在且只包含 HostBridge command 权限 反查 host_bridge_request 自动权限文件的 allow / deny 声明 同步桌面壳权限边界记录
This commit is contained in:
@@ -1029,25 +1029,30 @@ function extractNativeAppTauriInvokeCommands(source) {
|
||||
|
||||
function assertGeneratedPermissions(commandNames) {
|
||||
if (!fs.existsSync(generatedPermissionDir)) {
|
||||
return;
|
||||
throw new Error('desktop shell generated permissions directory is missing');
|
||||
}
|
||||
|
||||
const expectedPermissionFiles = new Set(
|
||||
commandNames.map((command) => `${command}.toml`),
|
||||
);
|
||||
for (const entry of fs.readdirSync(generatedPermissionDir, {
|
||||
const expectedPermissionFiles = commandNames
|
||||
.map((command) => `${command}.toml`)
|
||||
.sort();
|
||||
const permissionEntries = fs.readdirSync(generatedPermissionDir, {
|
||||
withFileTypes: true,
|
||||
})) {
|
||||
}).sort((left, right) => left.name.localeCompare(right.name));
|
||||
|
||||
assertSameList(
|
||||
permissionEntries.map((entry) =>
|
||||
`${entry.isDirectory() ? 'dir' : 'file'}:${entry.name}`,
|
||||
),
|
||||
expectedPermissionFiles.map((file) => `file:${file}`),
|
||||
'desktop shell generated permission files',
|
||||
);
|
||||
|
||||
for (const entry of permissionEntries) {
|
||||
if (entry.isDirectory()) {
|
||||
throw new Error(
|
||||
`desktop shell generated permissions must not include nested directory ${entry.name}`,
|
||||
);
|
||||
}
|
||||
if (!expectedPermissionFiles.has(entry.name)) {
|
||||
throw new Error(
|
||||
`desktop shell generated permission exposes an unexpected command: ${entry.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
const permissionFile = new URL(entry.name, generatedPermissionDir);
|
||||
const permissionSource = fs.readFileSync(permissionFile, 'utf8');
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
- 2026-06-18 桌面壳文件 bytes 校验:Tauri 图片 / 音频导入导出不得只信扩展名或 H5 声明 MIME;Rust 侧必须识别 PNG / JPEG / WebP、MP3 / MP4-M4A / WAV / OGG / WebM bytes 头部,要求导入文件扩展名对应 MIME 与真实 bytes 匹配,导出 payload 的 `mimeType` 与 `base64Data` 解码 bytes 匹配。不匹配返回 `invalid_request`,继续不暴露本机绝对路径或通用文件系统能力。配置检查和 cargo test 覆盖该边界。
|
||||
- 2026-06-18 移动壳文件 bytes 校验:Expo 图片 / 音频导入导出不得只信系统 picker 返回 MIME、文件扩展名或 H5 声明 MIME;移动壳必须识别 PNG / JPEG / WebP、MP3 / MP4-M4A / WAV / OGG / WebM base64 bytes 头部,要求导入 MIME 归一结果与真实 bytes 匹配,导出 payload 的 `mimeType` 与 `base64Data` 解码 bytes 匹配。不匹配返回 `invalid_request`,不会写入缓存文件、调起系统分享或把内容回传给 H5。移动图片导出还必须按 MIME 给系统分享 / 保存面板补齐 `.png` / `.jpg` / `.webp` 文件名扩展,避免缓存文件名与真实图片类型漂移。配置检查和移动壳测试覆盖该边界。
|
||||
- 2026-06-18 桌面壳 DevTools 边界:Tauri 主 WebView 配置必须显式 `devtools=false`,Cargo 依赖不得启用 Tauri `devtools` feature;桌面壳本地调试走普通浏览器和 Vite,不把 debug / release 桌面包变成可打开浏览器检查器的调试容器。配置检查会拒绝主窗口 DevTools 或 release feature 被重新打开。
|
||||
- 2026-06-18 桌面壳 Tauri 命令白名单:桌面壳源码、Tauri build manifest、主窗口 capability 和本地自动生成权限目录都只能暴露 `host_bridge_request` 一个受控 command;所有桌面能力继续在 Rust 内部按 HostBridge method 白名单分发,不新增可被 H5 直接 `invoke` 的 Tauri command,也不授予插件 JS guest API。检查脚本会拒绝多余 command、权限列表顺序漂移和残留的自动生成权限文件。
|
||||
- 2026-06-18 桌面壳 Tauri 命令白名单:桌面壳源码、Tauri build manifest、主窗口 capability 和本地自动生成权限目录都只能暴露 `host_bridge_request` 一个受控 command;所有桌面能力继续在 Rust 内部按 HostBridge method 白名单分发,不新增可被 H5 直接 `invoke` 的 Tauri command,也不授予插件 JS guest API。检查脚本会拒绝自动生成权限目录缺失、权限文件集合漂移、多余 command、权限列表顺序漂移和残留的自动生成权限文件。
|
||||
- 2026-06-18 桌面壳 capability 最小化:Tauri 主窗口 capability 只授予 `allow-host-bridge-request`,不得授予 `core:default`、`core:*:default`、任意 core 子权限或 dialog / fs / notification / opener / clipboard / deep-link / window-state 等插件权限。窗口、菜单、托盘、剪贴板、文件、通知和外链能力只能由 Rust 壳内部调用,再经 `host_bridge_request` 分发。
|
||||
- 2026-06-18 HostBridge request id replay:Expo 和 Tauri 壳都必须按 request id 回放首次完成结果;同 id 进行中的请求共享同一执行结果,已完成请求直接回放缓存响应,避免系统分享、外链、剪贴板、文件选择 / 保存、本地通知、窗口导航等宿主副作用被重复触发。两端配置检查和测试会锁住 replay 结构。
|
||||
- 2026-06-18 HostBridge request envelope 校验:共享契约提供 `isHostBridgeMethod` 与 `normalizeHostBridgeRequestId`,Expo 壳直接复用,Tauri 壳镜像同一白名单和 id 规则;空 id、控制字符 id、超长 id 和未知 method 都必须在 replay / 能力分发前返回 `invalid_request`,已知但当前壳未实现的登录 / 支付等 method 才返回 `unsupported_method`。
|
||||
|
||||
Reference in New Issue
Block a user