概览
dsh-browser-service
README / ZH
插件文档
目录摘要
dsh.pub 核对固定版本的组合包契约、运行时事实与分发语义;完整 README 请查看源仓库。
在 GitHub 阅读完整 READMELIMITATIONS
已知限制
### 安全模型 1. **只绑回环**:本机是 host 网络,`0.0.0.0` 上的 CDP 端口等于把浏览器完全交给主机上任意进程。内核永远带 `--remote-debugging-address=127.0.0.1`,对外只走回环代理;验收脚本会解析 `/proc/net/tcp` 检查这一点。 2. **`--no-sandbox` 是必需的**(容器 `NoNewPrivs=1` + seccomp 下 Chromium 沙箱起不来),因此**只访问可信站点**;需要更强隔离时把浏览器放进独立容器。 3. **`--disable-dev-shm-usage` 必需**(`/dev/shm` 只有 64M)。 4. 会话隔离必须用 incognito `BrowserContext`,不要复用默认上下文。 5. **公开端口要求凭据**:`Authorization: Bearer <token>`(每次守护进程启动随机生成,落在 0600 的 `service.json`)。代理只放行读元数据(`GET /json/version|/json/list|/json/protocol`)与 `/devtools/*`,挡掉 `/json/new|close|activate` 这类控制接口;`/json/version` 里的 `webSocketDebuggerUrl` 会被改写成代理自己的地址并附上 token,所以调用方(provider)不需要额外配置,也绕不开代理。内部内核端口仍只绑回环。**每条连接只认首个请求**:代理只在连接建立时解析一次请求头,所以非 WebSocket 请求一律按 `connection: close` 转发、响应后立刻关闭(否则同一连接上的后续请求就是免检的裸管道,F27)。 6. **保存路径准入**:`browser_screenshot` / `browser_download` 的 `savePath` 必须是绝对路径、不得覆盖已有文件,并且必须落在 `downloadDir` 内(不配置时=系统 Downloads 目录,见配置表;违规报 `BROWSER_SCREENSHOT_BLOCKED` / `BROWSER_DOWNLOAD_BLOCKED`)。这样接缝工具 schema 里那句「默认写进系统 Downloads 目录」才是真的,提示注入也没法让浏览器工具写任意路径。 7. 状态文件 0600、日志 0600,日志不记录页面内容。 8. **面板的写路由只对本机回环开放且要求同源**:实时窗口能点能打字,等于把浏览器交出去——非回环 403、跨站 403、方法白名单 405。 维护约定(改动这些是安全回归):上面的 1–4 与 6 请不要为了「能跑通」而放宽;验收脚本里对应断言就是为了拦住这种改动。 ### 已知限制 1. **一个 root 一个守护进程**(单例)。多个 profile 想共用内核要显式给同一个 `--root`;否则各自拉起一个。 2. **只监听回环**,同 uid 的其它进程读得到 `service.json` 里的 token(文档权限 0600,但同 uid 可读)。这是本机隔离,不是跨用户隔离。 3. **`--no-sandbox` 是必需项**(容器里 Chromium 沙箱起不来)⇒ 只访问可信站点;需要更强隔离就把浏览器放进独立容器。 4. **改插件代码或 profile patch 后必须重启 DSH**:完整 web profile 上 `patchReload: live` 会静默回滚(实测:探针条目 `applied` 后 6–7 ms 被 `disposed`,插件的 `apply` 根本没被调用;最小 profile 里热重载正常)。 5. **插件与 `browsersvc` 必须同版本升级**:v0.3.0 起公开端口要 Bearer token,旧插件 + 新守护进程会 401(F19 修的是冷启动重读 token)。 6. **工具面取决于依赖版本**:33 个 `browser_*` 来自 `dsh-builtin-browser`,上游增删工具时本包跟着变(本包只保证转出口形状一致、并把它写进验收)。 7. **守护进程会空闲自杀**(守护进程自身默认 15 分钟;本包自启默认 5 分钟,见配置表 `idleMs`;`--idle-ms` 允许 `1000..86400000`,即最长 24 小时)。**只有代理端口上没有任何连接时才会空闲**:所以 0.5.0 起插件在最后一个会话关闭后会**主动断开** CDP 连接——否则那条约 600 MB 的常驻浏览器永远不回收(P1)。DSH 侧下一次调用会自动把它拉回(F25),所以这是省内存的设计而不是故障;连「被下次调用拉起」也不想要,就 `dsh plugin remove` 卸载本包。 8. **`browser_execute` 传的是表达式语境**:传函数体会被当表达式求值并报 `page.evaluate: SyntaxError: Illegal return statement`,请传 `(...) => {...}` 或纯表达式。 9. **`browser_fill` 的 `fields[].selector` 是作用域不是定位器**:定位某个控件请用 `browser_click` / `browser_set_value` / `browser_check` 的 `target`。 10. **macOS / Windows 未测试**;仅 Linux(Debian 12 容器)实测。 11. **截图/下载默认只能写进系统 Downloads 目录**(`XDG_DOWNLOAD_DIR` → 家目录下存在的 `Downloads`/`下载`/`下載` → `~/Downloads`,对齐内置 provider)。要写进工作区或别处,就在 profile patch 的 `browser-cdp` 行 `config` 里显式配 `downloadDir`(patch **整行替换** `config`,覆盖时该行其它键要重述)。 12. **单个会话默认最多 5 个标签页**(配置 `maxTabs`,夹 `1..50`)。每个标签页是独立渲染进程,实测约 +93 MB;超限时 `browser_open {newTab:true}` 报 `BROWSER_TAB_LIMIT`,文案会列出当前标签,用 `browser_close_tab` 关掉不用的、或 `browser_reset_session` 清空本会话(P1)。 13. **面板设置存在浏览器本地**(`localStorage`):换机器/换浏览器要重新调;同一拍里连点两个设置按钮也不会互相覆盖(P8 改成传补丁 + 函数式更新)。 14. **随包技能在技能中心里显示成「系统内置」**:包内 `skills/` 由插件启动时注册的**技能提供者**提供(`source:'bundled'`、rank 600,与 `dsh-univer-office` 同形态),改技能正文不用重启。**同一层里 rank 小的先赢**,所以如果你之前用 `browsersvc skills --install` 落过盘(用户级 rank 400),那份会盖住内置的——跑一次 `browsersvc skills --uninstall` 再重启 DSH 就回到「系统内置」。落盘的同步只覆盖「我们自己写过且之后没人动过」的文件:你手工改过的同名技能会保留,同步会跳过并记一行 warn(要覆盖用 `browsersvc skills --install --force`)。
