升级插件安全策略、包管理和运行时能力

This commit is contained in:
2026-08-17 09:06:32 +08:00
parent 92e5c330f2
commit c3a8737fd6
50 changed files with 4409 additions and 2646 deletions
+53 -52
View File
@@ -1,8 +1,8 @@
# YMhut Box 插件开发说明
# YMhut Box manifest v3 插件
YMhut Box 插件是本地 WebView 插件包,用来扩展工具箱工具或插件页。插件运行在宿主隔离的 WebView 中,通过 `window.ymhut` Bridge 请求能力;插件不能直接访问应用核心资源、任意文件路径或系统浏览器
本地 HTML/CSS/JavaScript 是默认插件运行时。DOM、ES Module、Worker、Wasm、Canvas、WebAudio、`localStorage` 和 IndexedDB 不需要客户端权限,但仅存在于该插件自己的虚拟 HTTPS 原点中。客户端、系统、文件选择器、宿主存储、网络代理和外部服务能力只能通过 `window.ymhut` Bridge 使用
## 最小插件
## 最小包
```text
my-plugin/
@@ -13,78 +13,79 @@ my-plugin/
main.js
```
`README.md``README.txt``说明.md` 必须存在。`entry``resources` 和 surface 入口都必须留在插件目录内,不能使用 `../` 逃逸
插件包不能包含符号链接、目录联接或原生可执行文件。`entry`、surface 入口和资源必须位于包目录内
## manifest 核心字段
## manifest v3
```json
{
"$schema": "../../../docs/plugins/ymhut.plugin.schema.json",
"manifestVersion": 3,
"apiVersion": "2",
"id": "hello-tools",
"name": "Hello Tools",
"version": "1.0.0",
"author": "you",
"description": "A local YMhut Box plugin",
"description": "A local WebView plugin",
"entry": "index.html",
"permissions": ["Output", "Log", "Storage", "OpenExternal"],
"surfaces": [
{
"kind": "ToolboxTool",
"id": "hello",
"name": "Hello",
"description": "Toolbox entry",
"entry": "index.html",
"category": "plugin"
}
],
"runtime": "WebView",
"requirements": {
"minimumClientVersion": "2.0.6.2",
"minimumWindowsBuild": 17763,
"architectures": ["X64", "Arm64"]
},
"permissions": ["Http", "Output"],
"permissionReasons": {
"Http": "Read data from the declared public API.",
"Output": "Write the user-requested result to the host output panel."
},
"security": { "requiredPermissions": ["Http"] },
"network": {
"allowedOrigins": ["https://api.example.com"],
"openExternalOrigins": [],
"runToolIds": []
},
"surfaces": [{
"kind": "ToolboxTool",
"id": "hello",
"name": "Hello",
"description": "Toolbox entry",
"entry": "index.html",
"category": "plugin"
}],
"resources": ["index.html", "style.css", "main.js", "README.md"]
}
```
`id` 只允许字母、数字、点、短横线和下划线,不能以 `plugin:` 开头。工具箱挂载后的工具 ID 由宿主生成,格式是 `plugin:<pluginId>:<surfaceId>`
每项权限必须同时出现在 `permissions``permissionReasons``security.requiredPermissions` 中的权限未授权时插件不能启用;其余权限为可选权限,未授权时 Bridge 返回稳定错误码。权限用途、必需状态、范围、运行时或插件版本改变会使旧授权指纹失效
## 权限
权限默认关闭。manifest 只声明插件需要什么,用户仍要在插件页启用插件并授予权限。
- `Input`:读取或写入插件输入。
- `Output`:写入宿主输出区。
- `Log`:写入 `plugin:<pluginId>` 日志。
- `Storage`:访问插件私有 key-value 状态。
- `Http`:通过宿主请求 http/https。
- `Clipboard`:读写剪贴板文本。
- `FilePicker`:通过系统选择器打开或保存文件。
- `RunTool`:调用允许的内置工具。
- `OpenExternal`:打开 http/https 外链,默认进入安全浏览器。
- `NetworkDiagnostics`:请求本机网络诊断能力。
`Http` 必须声明精确 `network.allowedOrigins`;仅允许公网 `https://``wss://` 原点,不允许路径、通配符、HTTP、localhost、局域网或私网。`OpenExternal`/`OpenSystemBrowser` 使用 `openExternalOrigins``RunTool` 使用 `runToolIds`
## Bridge
```js
await window.ymhut.output.set("report");
await window.ymhut.storage.set("lastRun", JSON.stringify(data));
await window.ymhut.http.fetch({ url: "https://example.com/api" });
await window.ymhut.openExternal("https://example.com");
await window.ymhut.openExternal("https://example.com", { target: "system" });
const response = await window.ymhut.http.fetch({
url: "https://api.example.com/data",
method: "GET"
});
await window.ymhut.output.set(response.content);
```
普通外链默认进入 YMhut Box 安全浏览器。系统浏览器只作为显式动作使用,并继续受 `OpenExternal` 权限控制
协议为 `PluginHostProtocol v2`。每个 surface 会话绑定插件 ID、surface ID、虚拟原点和一次性令牌。插件脚本无法选择或伪造令牌。单消息上限 256 KiB,每会话最多 64 个并发调用,统一超时 30 秒;宿主 HTTP 响应上限 2 MiB
## 窗口与输出
常用稳定错误码:`permission_not_declared``permission_not_granted``permission_scope_denied``network_denied``session_invalid``payload_too_large``concurrency_limit``timeout`
插件内容区承载主 UI;宿主输出区用于报告、日志摘要、复制结果和调试信息。不要用输出区做主交互,也不要在插件页面使用全屏 fixed 遮罩、透明点击层或超高 z-index 覆盖宿主控件。
## Web 安全边界
插件需要适配主窗口内嵌和独立窗口内容区。建议使用响应式网格、可滚动表格和清晰空态;不要假设窗口固定尺寸
- 每个 surface 使用独立的 `https://p-<hash>.plugin.ymhut.invalid` 原点和独立 WebView2 数据目录
- 本地脚本、内联脚本、ES Module、Worker、Blob 和 Wasm 可用。
- 远程脚本、样式、字体、iframe、对象、导航、新窗口、下载、外部拖放和浏览器敏感权限被拒绝。
- 页面直接 `fetch`/WebSocket 与 `ymhut.http.fetch` 使用同一来源白名单;宿主 fetch 可兼容无 CORS API。
- 系统浏览器需要 `OpenSystemBrowser`,且每次调用都由宿主确认。
- Shell、Script、PowerShell、Node、Python 和插件自带原生程序不受支持。
## 安全边界
## 运行时与独立窗口
插件 WebView 只允许加载插件目录内本地资源。非本地导航会被拦截并交给安全浏览器。插件不能覆盖内置工具 ID、应用图标、开发者信息、关于页核心身份或内置 `Assets` 路径
`WebView` 是默认和正式运行时。Tauri 独立窗口仅使用应用自带宿主,默认关闭;它要求插件开发者模式、`ExternalRuntime` 授权和按插件版本保存的二次确认。Tauri 插件内容运行在独立的 `https://p-<hash>.localhost` 原点和插件私有 WebView2 数据目录中,应用宿主页只通过一次性、当前用户命名管道把 Bridge 请求转发给同一个权限宿主。会话令牌仅存在于原生宿主内,不进入插件 JavaScript。插件包不能携带或构建原生可执行文件,也不能访问 Tauri 全局 API
网络结果、排行榜和第三方数据都应标明不确定性,并在失败时显示降级状态
## 常见问题
- 加载失败:检查 manifest、README、entry 和 resources 是否存在且路径合法。
- 权限拒绝:检查 manifest 是否声明权限,以及插件页是否已授权。
- 外链打不开:只支持绝对 http/https URL,默认安全浏览器。
- 输出区遮挡:将输出区用于报告,不要用它承载主 UI。
- 独立窗口异常:不要调用浏览器弹窗 API 创建系统浏览器窗口。
旧清单自动降级为 `LegacyWebOnly`:本地 Web 内容可运行,Bridge、远程连接和外接运行时全部关闭。迁移步骤见 [MIGRATION-v3.md](MIGRATION-v3.md),完整边界见 [SECURITY.md](SECURITY.md)TypeScript 声明见 [ymhut.d.ts](ymhut.d.ts)