Overview
dsh-browser-service
README / EN
Package documentation
Registry summary
dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
### 安全模型 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`)。
