diff --git a/AGENT_INSTALL.md b/AGENT_INSTALL.md index e6116c759..45ae741de 100644 --- a/AGENT_INSTALL.md +++ b/AGENT_INSTALL.md @@ -111,8 +111,18 @@ for Chrome and other Chromium browsers, [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg) for Microsoft Edge — and ask them to install it on the computer with that browser. -- **Local:** ask the user to open the popup, enable the connection and confirm the - port matches the local daemon; wait for the connected status. +- **Local:** enable the connection and continue when connected. Pairing is optional; + an unpaired warning does not block installation or browser use. Do not make the + user pair or update the other component just to complete setup. Explain the + warning and offer pairing when the user wants connection identity verification. + Run `bsk daemon pair` with the intended daemon's `BSK_HOME` and ask the user to + paste its private link into **Connection settings → Pairing link**. The command + reuses or starts the daemon; with `BSK_AUTO_START=0`, the host must start it first. + Keep the link out of logs, issues and shared transcripts. Successful pairing + shows **Connected · Verified**. On `already_paired`, retain the current pairing; + use `--replace BROWSER_ID` only for an intended replacement. An already-paired + browser must not automatically skip verification after an authentication failure. + See [local pairing](docs/local-pairing.md). - **Remote:** ask the user to select **Remote connection**, paste the pairing link and save it. Follow the [remote verification steps](docs/remote-extension-connection.md#pair-and-verify); installing the extension or generating a link alone does not establish a connection. diff --git a/CHANGELOG.md b/CHANGELOG.md index 70772fa2b..e8e33751d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,36 @@ All notable changes to BrowserSkill will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/). -Starting from 0.2.0, CLI / Extension / DSH Plugin share the same version number. +CLI, Extension and DSH Plugin may release separately during staged rollouts; +protocol compatibility determines which versions can connect. + +## [Unreleased] + +### Added + +- Local pairing with mutual proofs, durable key rotation and interruption recovery. + Paired connections verify the daemon before sending business traffic; activation + invalidates the original link. Device revocation and browser registration are + serialized, and successful revocation completes live connection cleanup. +- `bsk daemon pair --replace`, local device listing/revocation, `daemon rotate` + and `daemon trust-local on|off`; status and doctor expose pairing guidance. +- Extension 0.4.2 pairing settings, staged verification, ten-language guidance, + explicit bypass confirmation and retained remote grants when using local mode. + Pairing is optional for new installs and upgrades; unpaired connections remain + usable with an identity warning and a link to the official security overview. + Paired connections and saved recovery candidates never automatically downgrade. +- `bsk daemon pair` reuses or starts the daemon before returning a usable link. + Explicit Required mode remains available; unverified connections cannot claim + an existing paired identity under the default policy. + +### Changed + +- Extension 0.4.3 removes obsolete migration flags and version gates while keeping + pairing optional. There is no automatic enforcement deadline. + +- Initial pairing-capable CLI defaults to Warn during distribution. Required mode + and extension 0.4.3 migration retirement have separate release prerequisites; + see the [local pairing rollout](docs/local-pairing.md#release-prerequisites). ## [0.4.1] - 2026-11-02 diff --git a/README.md b/README.md index f652d7eae..7c63280c0 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ If an already-running agent cannot find `bsk`, restart it to pick up the new PAT #### 2. Connect the extension -Install it from the [Chrome Web Store](https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi) or [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg). Open its popup, enable the local connection, and check its status after starting the CLI. +Install it from the [Chrome Web Store](https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi) or [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg), enable the connection and start using it. Local pairing is optional: an unpaired connection stays usable and shows an identity warning. To verify the connection, run `bsk daemon pair` and paste its link into **Connection settings → Pairing link**. Pairing is remembered across restarts and upgrades; a paired connection never automatically skips verification after a failure. See [local pairing](docs/local-pairing.md). #### 3. Install the skill for your agent diff --git a/README.zh-CN.md b/README.zh-CN.md index a36a5fb46..584534d00 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -128,7 +128,7 @@ bsk --version #### 2. 连接扩展 -从 [Chrome Web Store](https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi) 或 [Edge 加载项商店](https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg) 安装扩展。打开弹窗,开启本地连接,在 CLI 启动后检查连接状态。 +从 [Chrome Web Store](https://chromewebstore.google.com/detail/hhcmgoofomhgciiibhipgmgkgnoenaoi) 或 [Edge 加载项商店](https://microsoftedge.microsoft.com/addons/detail/browserskill/emacgiaaaiojkkpkddmmdfhmokgmnikg) 安装扩展,开启连接后即可使用。本机配对是可选的:未配对仍可正常使用,扩展会提示连接身份未经验证。如需配对,运行 `bsk daemon pair`,将链接粘贴到**连接设置 → 配对链接**并保存。重启和升级后无需重复配对;已配对后验证失败不会自动跳过验证。详见[本机配对指南](docs/local-pairing.zh-CN.md)。 #### 3. 给 Agent 安装 skill diff --git a/apps/extension/PRIVACY.md b/apps/extension/PRIVACY.md index fc233c53a..3271ed1b2 100644 --- a/apps/extension/PRIVACY.md +++ b/apps/extension/PRIVACY.md @@ -1,6 +1,6 @@ # BrowserSkill — Privacy Policy -**Last updated:** October 30, 2026 +**Last updated:** November 2, 2026 This Privacy Policy describes how the **BrowserSkill** browser extension (the "Extension") handles information when you install and use it. BrowserSkill is published as part of the open-source [BrowserSkill](https://github.com/Tencent/BrowserSkill) project. The source code is publicly auditable. @@ -65,7 +65,7 @@ The Extension requests the following Chrome permissions. Each is used solely for - **`notifications`** — Request user approval before borrowing a user-owned tab when browser confirmation is enabled, alert the user when an active task requests human assistance when enabled, and notify the user when an incompatible running daemon prevents connection. Notifications support the user's browser task and are not used for advertising or promotional messages. - **`downloads`** — Save screenshots, including full-page captures, and recorded MP4 videos when the user explicitly exports them. Track the requested video's download to distinguish successful saves from canceled or failed saves and release its temporary download URL. Also correlate and route the one browser download initiated by an active `bsk download` command. If that claimed transaction fails, BrowserSkill cancels an in-progress file or removes its completed temporary browser file. It is not used to enumerate download history or alter unrelated downloads. - **`offscreen`** — Run the video encoder worker and manage temporary video download URLs in an extension-owned offscreen document, allowing explicitly started recording and MP4 finalization to continue when the popup closes. This does not capture other tabs, the desktop or audio. -- **`storage`** — Persist a random instance ID, optional label, and feature preferences in `chrome.storage.local`, and track pending video exports in `chrome.storage.session`. Remote credentials, website debugging history and the video catalog are stored separately in extension-origin IndexedDB; video files and recovery fragments use the origin-private file system (OPFS). +- **`storage`** — Persist a random instance ID, optional label, and feature preferences in `chrome.storage.local`, and track pending video exports in `chrome.storage.session`. Local and remote credentials, local verification settings, website debugging history and the video catalog are stored separately in extension-origin IndexedDB; video files and recovery fragments use the origin-private file system (OPFS). - **Host permission ``** — Inject a small status overlay (showing "Agent Active") on pages controlled by the agent, and enable automation across whatever sites the user directs the agent to. Remote connections also use this permission for the selected endpoint. Remote page-content access requires a task-created or explicitly borrowed tab. ## 6. Where Data Goes @@ -98,7 +98,7 @@ When explicitly configured by the user or agent during an active capture, HTTP r - Operation audit is separate from website debugging and is off by default. When enabled, the selected daemon stores task and operation metadata in `BSK_HOME/audit` (by default `.bsk/audit` under the user home directory). Records include timestamps, tool types, website origins, element names with basic redaction, statuses, and error codes. Input values, page bodies, screenshots, scripts, and file contents are excluded from operation audit; these exclusions do not apply to website debugging history described above. Ended tasks are retained for 30 days and pruned when history is loaded, audit is enabled, a task starts, or the task list is queried. Users can export or delete ended tasks from the audit page. Exported copies are not automatically removed. -- Remote endpoint and device credentials remain in extension-origin IndexedDB until the user selects Local connection, clears extension storage or uninstalls. The server retains device grants until revoked; expired grants cannot connect. Disconnecting does not delete results or audit records already held by a server. +- Local and remote credentials remain in extension-origin IndexedDB when switching modes, until replaced, extension storage is cleared or the extension is uninstalled. Uncommitted staged local records expire after ten minutes. Local mode does not renew retained remote grants. The server retains device grants until revoked; expired grants cannot connect. Disconnecting does not delete results or audit records already held by a server. ## 8. User Control @@ -122,7 +122,11 @@ The Extension is a developer tool and is not directed at children under 13. ## 10. Security -Local mode trusts processes able to bind the configured loopback port. Remote mode requires explicit pairing and encrypted transport, except for loopback development. The built-in server stores credential hashes, validates connections, supports rotation and closes connections on revocation or expiration. Third-party gateways are responsible for implementing the same authorization lifecycle and isolating device routing. +Paired local connections require mutual cryptographic proofs before browser control. Local keys and pending rotation candidates are stored in extension-origin IndexedDB, inaccessible to website content scripts; the daemon stores private local pairing records in its bsk home. Pairing-link secrets stay in the URL fragment and are never sent as request paths, query parameters or headers. + +Local pairing is optional for fresh installs and upgrades. Unpaired connections remain usable and show an identity warning; they retain the risk of local peer impersonation. Once paired, verification failures never automatically fall back to an unverified connection. Explicitly skipping verification is a separate user choice and keeps a warning visible. Pairing credentials survive mode switches, and retained remote grants are not renewed while using local mode. See [local pairing](../../docs/local-pairing.md). + +Remote mode requires explicit pairing and encrypted transport, except for loopback development. The built-in server stores credential hashes, validates connections, supports rotation and closes connections on revocation or expiration. Third-party gateways are responsible for implementing the same authorization lifecycle and isolating device routing. Remote page reads and operations require task-owned tabs; merely moving a user tab into an Agent Window does not authorize it. Borrowing follows the confirmation preference controlled in the browser. Treat a paired server as trusted to operate your browser profile and signed-in websites. Browser profile files, server data and TLS keys must remain private to trusted local users. See [remote browser connections](../../docs/remote-extension-connection.md) for deployment details. diff --git a/apps/extension/PRIVACY.zh-CN.md b/apps/extension/PRIVACY.zh-CN.md index 8756532cd..6b155ec62 100644 --- a/apps/extension/PRIVACY.zh-CN.md +++ b/apps/extension/PRIVACY.zh-CN.md @@ -1,6 +1,6 @@ # BrowserSkill 隐私政策 -**最后更新:** 2026 年 10 月 30 日 +**最后更新:** 2026 年 11 月 2 日 本隐私政策说明 **BrowserSkill** 浏览器扩展(下称"本扩展")在您安装和使用过程中如何处理信息。BrowserSkill 作为开源项目 [BrowserSkill](https://github.com/Tencent/BrowserSkill) 的一部分发布,源代码完全公开,可供审计。 @@ -31,7 +31,7 @@ BrowserSkill 让用户指定的 AI 助手通过 `bsk` 命令行工具操作 Chro | **共享控制数据** | 受控页面的当前观察结果、页面及表单变化、有数量限制的手动活动事件、焦点和控制状态,以及观察上下文标识。 | 用于协调人与 Agent 的操作,在手动交互期间让出控制权,并拒绝基于过时页面状态的操作。 | | **网站调试数据** | 采集期间选定标签页的请求 URL、方法、请求头、可获取的请求与响应正文、状态、耗时、错误及相关网络元数据;控制台消息;Agent 操作与受支持的手动输入、点击、提交和导航事件;有数量及长度限制的可见页面文本、表单字段值、页面状态和性能数据。还会记录已配置的 HTTP 规则和请求重放结果。 | 用于检查和复现网站行为,将操作与请求及页面变化关联,分析性能,以及查看或导出调试历史。 | | **标签页与窗口元数据** | 标签页 ID、URL、标题和窗口 ID,包括为选择借用目标而列出的用户标签页。 | 用于将自动化指令发送到正确的标签页/窗口。 | -| **扩展本地存储** | 一个随机生成的 8 位十六进制实例 ID、可选的用户自定义标签、功能偏好(包括审计开关),以及可选的远程端点和设备凭据。 | 用于识别此浏览器实例并恢复用户设置。 | +| **扩展本地存储** | 一个随机生成的 8 位十六进制实例 ID、可选的用户自定义标签、功能偏好(包括审计开关),以及可选的本机和远程端点及设备凭据。 | 用于识别此浏览器实例并恢复用户设置。 | | **Agent 请求的文件传输** | 用户明确提供给 `bsk upload` 的本地文件,以及单次 `bsk download` 操作产生的文件。 | 用于将任务文件附加到网页,或将浏览器生成的下载交给发起请求的本地 Agent。 | | **用户请求的截图导出** | 用户在预览页选择保存图片时的截图数据(包括长截图)及建议文件名。 | 用于通过浏览器的“另存为”对话框保存用户请求的图片。 | | **任务视频录制** | 选定任务标签页的渲染画面、无声 MP4,以及标签页标题、任务/标签页 ID、时间、时长、画质、大小、完成状态和中断原因等元数据。 | 用于录制明确请求的任务、恢复可播放的部分视频,并让用户预览、导出或删除结果。 | @@ -65,7 +65,7 @@ BrowserSkill 让用户指定的 AI 助手通过 `bsk` 命令行工具操作 Chro - **`notifications`** —— 浏览器借用确认开启时,请求用户授权借用已有标签页;在允许请求人工协助时提醒用户处理相关步骤;正在运行的 daemon 不兼容、导致无法连接时提示用户。通知仅服务于用户的浏览器任务,不用于广告或推广。 - **`downloads`** —— 用户主动导出时保存截图(包括长截图)和录制的 MP4 视频。跟踪该视频的下载结果,区分成功、取消与失败,并释放临时下载 URL。同时关联和处理当前 `bsk download` 命令发起的单次下载。如果已认领的传输失败,BrowserSkill 会取消进行中的下载,或删除已完成的浏览器临时文件;不会枚举下载历史或更改无关下载。 - **`offscreen`** —— 在扩展自身的离屏文档中运行视频编码 worker,并管理临时视频下载 URL,让明确启动的录制和 MP4 生成可以在弹窗关闭后继续进行。不用于采集其他标签页、桌面或音频。 -- **`storage`** —— 在 `chrome.storage.local` 中保存随机实例 ID、可选标签及功能偏好,在 `chrome.storage.session` 中跟踪尚未完成的视频导出。远程凭据、网站调试历史和视频目录与这些设置分开,保存在扩展来源的 IndexedDB 中;视频文件及恢复片段保存在来源私有文件系统(OPFS)中。 +- **`storage`** —— 在 `chrome.storage.local` 中保存随机实例 ID、可选标签及功能偏好,在 `chrome.storage.session` 中跟踪尚未完成的视频导出。本机与远程凭据、本机迁移和验证设置、网站调试历史和视频目录与这些设置分开,保存在扩展来源的 IndexedDB 中;视频文件及恢复片段保存在来源私有文件系统(OPFS)中。 - **主机权限 ``** —— 在助手控制的页面上注入状态浮层(提示"代理已激活"),并支持用户引导助手访问任意网站。远程连接也使用此权限访问用户选择的端点。远程页面内容访问要求标签页由任务创建或明确借用。 ## 6. 数据流向 @@ -98,7 +98,7 @@ BrowserSkill 让用户指定的 AI 助手通过 `bsk` 命令行工具操作 Chro - 操作审计独立于网站调试,默认关闭。开启后,所选守护进程会在 `BSK_HOME/audit`(默认用户目录下的 `.bsk/audit`)保存任务与操作元数据,包括时间、工具类型、网站来源、经过基础脱敏的元素名称、状态和错误码;操作审计不保存输入值、页面正文、截图、脚本或文件内容,这些排除项不适用于上述网站调试历史。已结束的任务保留 30 天,在服务加载、开启审计、创建任务或查询列表时清理。用户可在审计页导出或删除已结束的记录。导出的副本不参与自动清理。 -- 远程端点和设备凭据单独保存在扩展来源的 IndexedDB 中,直到用户切回本地连接、清除扩展存储或卸载扩展。普通设置仅保存不含凭据的版本标记。服务端授权保留至撤销,过期授权不能连接;断开连接不会删除服务器已收到的结果和审计记录。 +- 本机与远程凭据在切换模式时继续保留在扩展来源的 IndexedDB 中,直到被替换、清除扩展存储或卸载扩展。未提交的本机暂存记录在十分钟后过期;本机模式不续期远程授权。服务端保留设备授权,直到被撤销;过期授权无法连接。断开连接不会删除服务端已持有的结果或审计记录。 ## 8. 用户控制 @@ -122,7 +122,11 @@ BrowserSkill 让用户指定的 AI 助手通过 `bsk` 命令行工具操作 Chro ## 10. 安全性 -本地模式信任能够绑定所配置回环端口的进程。远程模式要求主动配对和加密传输,回环开发场景除外。内置服务端保存凭据哈希,校验连接,支持凭据轮换,并在授权撤销或过期后断开连接。第三方网关需要实现同一套授权生命周期与设备路由隔离。 +已配对的本机连接在控制浏览器前要求双方完成密钥证明。本机密钥及待定换钥记录保存在扩展来源的 IndexedDB 中,网页内容脚本无法读取;daemon 在私有 bsk home 中保存本机配对记录。链接中的密钥仅位于 URL 片段,不会作为请求路径、查询参数或请求头发送。 + +本机配对对新安装和升级用户均为可选。未配对连接仍可使用,扩展提示连接身份未经验证;这种连接保留被本机程序冒充的风险。已配对后,验证失败不会自动退回未验证连接。主动跳过验证是单独的用户选择,并保留常驻警告。切换模式会保留配对;使用本机模式期间,不会续期已保存的远程授权。详见[本机配对说明](../../docs/local-pairing.zh-CN.md)。 + +远程模式要求主动配对和加密传输,回环开发场景除外。内置服务端保存凭据哈希,校验连接,支持凭据轮换,并在授权撤销或过期后断开连接。第三方网关需要实现同一套授权生命周期与设备路由隔离。 远程读取和操作仅允许访问任务创建或明确借用的标签页;把用户标签页移入代理窗口本身不会授予权限。借用遵循浏览器用户控制的确认偏好。请仅配对有权操作您浏览器配置及已登录网站的可信服务器,保护好浏览器配置、服务端数据和 TLS 密钥。部署细节见[远程浏览器连接](../../docs/remote-extension-connection.md)。 diff --git a/crates/bsk-cli/skill/references/environment.md b/crates/bsk-cli/skill/references/environment.md index 37d9b3483..9b2b1459c 100644 --- a/crates/bsk-cli/skill/references/environment.md +++ b/crates/bsk-cli/skill/references/environment.md @@ -125,3 +125,12 @@ If installation or browser-side connection steps are needed, direct the user to the [extension setup guide](https://github.com/Tencent/BrowserSkill/blob/main/AGENT_INSTALL.md#4-connect-the-browser-extension). After setup or repair, rerun `bsk doctor` with the same environment and address any remaining `fail` checks before starting a session. + +On `pairing_required` or a local-pairing hint, run `bsk daemon pair` with that +same environment and have the user paste the private link into extension +connection settings. Wait for Connected / Verified, then recheck doctor. +Do not put pairing secrets in logs or shared reports. `already_paired` preserves +the current connection; use `pair --replace BROWSER_ID` only for an intended +replacement. `replace_mismatch` needs a normal link for the new profile; revoke +an unused old device separately. Never enable skip/trust-local automatically. +Independent bsk homes require separate pairings. diff --git a/docs/architecture.md b/docs/architecture.md index b633e71ba..175d2a1c3 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -52,7 +52,11 @@ Key modules: - In local mode, listens on loopback WebSocket (default **52800**, configurable with `bsk daemon start --port`) for extensions. The extension popup saves the matching connection port; saving ends existing sessions and reconnects when enabled. - Server mode supports authenticated remote extension connections with device pairing, renewal and revocation. Native TLS or a TLS reverse proxy provides WSS; the deployment supervisor owns server restarts. -- Validates `Origin: chrome-extension://…` on handshake. +- Validates `Origin: chrome-extension://…` on upgrade and authenticates paired + local peers with nonce-bound HMAC proofs before the business handshake. + Local pairing is optional; unpaired peers retain the legacy handshake. Paired + identities cannot be claimed by unverified peers unless TrustLocal is explicitly + enabled. Origin is transcript context, not authorization. See [local pairing](local-pairing.md). - Maintains `browsers` (connected extensions) and `sessions` (Agent Window bindings). - **Per-session queue** serializes tool calls targeting one session. - Forwards `tool.*` RPCs to the correct extension connection. @@ -62,6 +66,8 @@ State files under `~/.bsk/`: | File | Purpose | | --- | --- | | `daemon.lock` | Advisory lock — single daemon instance | +| `local-pairings.json` | Local daemon identity, active/unactivated devices and pending key transactions; private atomic storage | +| `settings.json` | Persistent local authentication policy | | `daemon.json` | `{ sock_path, pid, ws_port, version }` | | `daemon.log` | Rolling trace log | | `daemon.pid` | PID for status/doctor | @@ -259,3 +265,28 @@ directory, registered with a module-relative `resourceBase` so agents can read r on demand regardless of their working directory. CI validates local links, entry point budgets, Cargo contents and the actual npm archive, including resource resolution from the unpacked runtime. + +## Local authorization lifecycle + +The extension first sends `system.ping` with `params.local_auth`. The daemon +selects an offered active or staged credential and proves possession of its key; +only then does the extension send its client proof. No business frames, registry +updates or session purges happen before authorization succeeds. + +Activation and requested rotation persist a candidate, send `ready.rotation`, +wait for the extension's strict IndexedDB commit and confirmation, then durably +commit before sending `committed`. Recovery uses `ready.commit`, the saved key, +and the current connection transcript. The extension promotes the candidate +strictly before its business handshake. Exactly one final message is accepted. + +Device gates serialize the prelude, rotation, final authorization plus registry +insertion, and revocation. Replacement activates the new record and revokes the +old one atomically; socket and session cleanup finishes before success is reported. +The daemon owns its loaded store only after acquiring `daemon.lock`. Online +maintenance uses IPC; offline maintenance holds that same lock. Persistent +revocation is also checked every second without blocking the async executor. + +The extension shares IndexedDB version 2 between independent `connection`, `local` +and `migration` stores. Keys never enter `chrome.storage`, URLs sent over the +network, or logs. A staged verifier has its own socket and no business dispatcher. +The business transport reports connected only after its authenticator finishes. diff --git a/docs/local-pairing.md b/docs/local-pairing.md new file mode 100644 index 000000000..a62b285ad --- /dev/null +++ b/docs/local-pairing.md @@ -0,0 +1,158 @@ +# Local browser pairing + +Local pairing is optional. Fresh installs, existing users and independent CLI or +extension upgrades can keep using an unpaired local connection. The popup shows +**Connected · Unpaired**, explains the identity risk and offers **Pair**. Its +circled warning icon opens the [official security overview](https://browserskill.weixin.qq.com/#security). +There is no migration deadline or required upgrade order for unpaired local use. + +## Why pair? + +An unpaired connection does not prove who is at the other end. Malicious local +software may impersonate a daemon or browser peer. Pairing adds mutual identity +proof before browser registration or tool traffic. It is an optional security +improvement; leaving it off retains the impersonation risk. + +An existing pairing never falls back automatically when verification fails, +including when a peer claims to be an old daemon. Saved candidate keys are also +verified because the daemon may already have committed the pairing. A failed or +expired unused link does not disable an otherwise unpaired connection. + +## Pair and verify + +1. Run `bsk daemon pair` with the same `BSK_HOME` used by your agent. It reuses the + running daemon or starts one through the normal auto-start path. If your host + sets `BSK_AUTO_START=0`, start the host-managed daemon first; the command reports + that requirement instead of printing an unusable link. +2. Open the extension's connection settings and paste the complete link into + **Pairing link**. Local and remote links select the appropriate tab automatically. +3. Save and wait for **Connected · Verified**. Normal restarts and upgrades retain + the pairing. You do not need to pair before every task. + +Trying to pair uses a separate verification connection; a rejected or expired +link leaves the existing connection available. Successful pairing switches to the +verified connection. If either component predates pairing, update it when you +choose to pair; ordinary unpaired use does not require that update. An old +extension keeps working but cannot show the new popup warning until updated. + +A local link looks like `ws://127.0.0.1:52800/#bsk-local.v1.…`. It includes the +port and a one-use secret. Keep it private. Unused links expire after five minutes. +Activation changes the key before the browser becomes available, so the original +link cannot open another connection. + +The extension retains up to eight daemon identities. Independent `BSK_HOME` +directories have different identities and need separate pairings. Changing a +port does not change a daemon's identity. Once the browser has an active pairing, +connecting it to another daemon requires pairing with that daemon or explicitly +skipping verification; an unknown peer cannot turn verification off. + +## Maintain devices + +```sh +bsk daemon devices +bsk daemon rotate DEVICE_ID +bsk daemon revoke DEVICE_ID +bsk daemon revoke --all +bsk daemon pair --replace BROWSER_ID +``` + +`devices` lists local and remote records without keys. `rotate` requests a key +change on the next authenticated connection. `revoke` accepts a local device ID +or its bound browser ID. Successful local revocation closes registered sockets, +settles pending calls and removes sessions before returning. `--all` also revokes +remote grants and unused links; already completed page actions cannot be undone. + +An ordinary link cannot replace an existing pairing for the same browser +instance. On `already_paired`, keep the current connection, or explicitly create +a replacement link with `--replace` if replacement is intended. The popup warns +that successful replacement ends current tasks. It verifies the staged link on +a separate connection and keeps the active pairing until the replacement commits. +A `replace_mismatch` means the link targets another browser instance; use a normal +link for a new profile and revoke an unused old device separately. + +Maintenance commands use the running daemon's IPC. When the daemon is absent, +they hold `daemon.lock` while editing persistent state. A locked but unavailable +daemon causes a bounded wait and an error; commands never fall back to editing +its live files. Do not edit `local-pairings.json` by hand. + +## Connection problems + +| Popup or CLI state | Action | +| --- | --- | +| Pairing required / `pairing_required` | Run `bsk daemon pair` in the intended home and paste the link into that profile. | +| Service failed verification | Run `bsk doctor`; check the port and whether the bsk home was reset. Use a new link only after confirming the intended service. | +| bsk too old | Run `bsk update`, restart a host-managed daemon through its owner, then retry. Existing pairings remain valid. | +| Device busy | Wait for the other verification attempt to finish, then retry. | +| `already_paired` | Keep the current pairing, or generate an explicit replacement link. | +| `replace_mismatch` | Use a normal link for a new profile; the old device has not been revoked. | + +Authentication failures back off from 30 seconds to five minutes. **Retry** starts +an immediate attempt. Interrupted activation/rotation normally resumes with its +saved candidate key and a fresh connection. A verifier retains a candidate after +an ambiguous commit reply, because deleting it could lose a successful replacement. +Staged links without a saved candidate expire after ten minutes in the extension. +Once a candidate is saved, both keys survive cleanup and startup until authenticated +recovery succeeds; elapsed time cannot prove whether the daemon committed it. + +## Explicitly skipping verification + +In the extension's **Advanced** settings, **Skip local verification** requires a +confirmation. The daemon must separately allow it with `bsk daemon trust-local on`. +This permits local programs to impersonate either endpoint. The popup keeps an +unverified warning visible; `bsk doctor` warns about trust-local mode. Skipping +retains stored pairings but does not use them or send an authentication probe. + +Use **Restore verification** in the extension and run +`bsk daemon trust-local off` to restore both sides. The latter selects Required +mode immediately. Agents must not enable skipping or trust-local as an automatic +response to an authentication failure. + +Switching from remote to local ends current tasks but retains the remote grant. +It is not renewed while local mode is selected. Before its displayed expiry, +you can switch back without a new link; after expiry, pair with the server again. + +## Compatibility and security boundaries + +The CLI defaults to **Warn**: unpaired local connections remain available without +an authentication probe. The extension uses the same rule for fresh installs and +upgrades. Eligibility flags, previous versions and compatibility deadlines do not +control whether an unpaired browser can connect. + +After activation, an unverified connection cannot claim that paired browser's +identity, including after its key is revoked. This does not force unrelated old +extensions to pair. Explicit TrustLocal mode bypasses this protection; the daemon +and extension both retain their separately confirmed bypass controls. + +Users who want to reject every unpaired connection can explicitly run +`bsk daemon trust-local off`, which selects **Required**. Neither installing nor +pairing a browser automatically enables that policy for other browsers. + +Local pairing protects the connection, not the OS account or websites. It does +not defend against a process that can read the user's browser profile or bsk +home, or against an explicitly trusted server. Local and remote credentials are +not interchangeable; remote deployments still require TLS and device isolation. + +The v1 handshake does not encrypt subsequent loopback traffic or prevent a +transparent relay from reading or changing it. An attacker with both the original +pairing link and its first handshake transcript can derive the next key. A stolen +unused link can also be activated first by someone else. Keep links private and +use them promptly; these limitations require a separately reviewed encrypted +record protocol and key exchange to address. + +## Release validation + +Extension 0.4.2 introduces optional pairing. The 0.4.3 cleanup removes obsolete +migration state without withdrawing unpaired access. These are extension release +versions; CLI and extension updates do not need to arrive together. + +Before release, verify new and upgraded profiles against both pre-pairing and +current daemons, plus paired reconnect, candidate recovery, revocation and explicit +Required/TrustLocal modes. Validate the Chrome and Edge store builds on supported +platforms. Publishing a store version is not evidence that every user has updated; +there is no automatic enforcement stage in this plan. + +For process-level integration tests, build the CLI and set `BSK_TEST_BINARY` to +its absolute path when running the extension's `local-auth-daemon.test.ts` test. +Set `BSK_TEST_OLD_BINARY` to a pre-pairing executable for the legacy compatibility +test. Tests use temporary homes and random ports; never point them at a user's +running daemon or reuse the user's browser profile. diff --git a/docs/local-pairing.zh-CN.md b/docs/local-pairing.zh-CN.md new file mode 100644 index 000000000..5089de9c7 --- /dev/null +++ b/docs/local-pairing.zh-CN.md @@ -0,0 +1,33 @@ +# 为什么建议本机配对? + +本机配对是可选的。新安装、老用户升级、只升级 CLI 或只升级扩展,都可以继续使用未配对连接。扩展显示“已连接 · 未配对”,提醒连接身份尚未验证;不会因此禁用功能,也没有强制迁移期限。 + +## 配对解决什么问题 + +本机连接也需要区分连接方的身份。未配对时,恶意本机程序可能冒充 bsk 或浏览器连接方。配对让双方在开始浏览器操作前证明身份,降低这类冒充风险。 + +配对不等于系统绝对安全:它不能防御可以读取浏览器配置或 bsk 凭据文件的程序,也不会加密后续所有本机流量。未配对仍保留原有的身份冒充风险。详细协议边界见[英文指南](local-pairing.md#compatibility-and-security-boundaries)。 + +## 如何配对 + +1. 在运行 Agent 的同一套 `BSK_HOME` 下执行 `bsk daemon pair`。命令会复用或启动本机 daemon;宿主设置了 `BSK_AUTO_START=0` 时,先通过宿主启动 daemon。 +2. 打开扩展的“连接设置”,把输出的完整链接粘贴到“配对链接”,点击保存。 +3. 显示“已连接 · 已验证”后完成。正常重启和升级会保留配对,不需要每次任务重复操作。 + +链接包含一次性凭据,未使用时五分钟过期,请勿公开。如果主动配对时提示版本不支持,升级对应的 CLI/正在运行的 daemon 或扩展再试;普通未配对使用不要求同步升级两端。 + +尝试配对使用独立连接。链接过期或被拒绝时,原连接保持可用;配对成功后切换到验证连接。不同浏览器配置、不同 `BSK_HOME` 分别配对。 + +## 已配对后验证失败 + +已经配对的浏览器不会因为对方声称是旧版本、配对记录被重置或验证失败而自动退回未验证连接。先确认连接的是预期的 bsk,运行 `bsk doctor` 检查;需要替换配对时使用 `bsk daemon pair --replace BROWSER_ID`。 + +待恢复的配对也需要验证:本机保存的候选密钥可能已在 daemon 生效,不能因等待时间较长而丢弃。 + +## 是否需要强制所有连接配对 + +默认不强制。配对一个浏览器也不会要求其他未配对浏览器同步迁移。 + +希望自行启用严格模式时,运行 `bsk daemon trust-local off`,daemon 会拒绝未配对连接。高级设置中的“跳过本机验证”和 `bsk daemon trust-local on` 是主动绕过验证的选项,不能由程序在验证失败后自动开启。 + +远程连接的配对要求不受这个本机可选策略影响。 diff --git a/docs/remote-extension-connection.md b/docs/remote-extension-connection.md index a4723e431..3a2eb52dc 100644 --- a/docs/remote-extension-connection.md +++ b/docs/remote-extension-connection.md @@ -17,7 +17,16 @@ bsk daemon start # Equivalent: bsk daemon start --mode local ``` -It listens on loopback. Existing CLI commands and extension port settings continue to work. Select **Local connection** in the extension to leave a remote connection; this ends its current tasks. +It listens on loopback and permits unpaired local connections by default. Local +pairing is optional: run `bsk daemon pair` and paste the local link into the +extension’s connection settings to verify identity. See [local pairing](local-pairing.md). +Remote connections still require pairing; local keys and remote grants are separate. + +Select **Local connection** to leave a remote connection; this ends its current +tasks but keeps its private authorization. Local mode does not renew the remote +grant. You can switch back before the displayed expiry without a new link; an +expired grant requires pairing again. The same input recognizes local and remote +links automatically. ## Standalone server diff --git a/docs/sandboxed-agents.md b/docs/sandboxed-agents.md index 288add3d4..aa6f6c67d 100644 --- a/docs/sandboxed-agents.md +++ b/docs/sandboxed-agents.md @@ -66,6 +66,12 @@ necessarily select the directory that the agent's user expects. Configure `BSK_HOME` explicitly on both sides instead of guessing a username or changing the process's global `HOME`. +Local pairing is optional. Each independent `BSK_HOME` has its own identity. +If you choose to pair, pair the intended browser with each home you use; changing directories to bypass an error does not +reuse authorization. Run `bsk daemon pair` with the same environment as status +and session commands, then have the user paste its private link in the extension. +See [local pairing](local-pairing.md). + ## 2. Check for an existing daemon From the agent's command environment, disable implicit startup and check the diff --git a/packages/dsh-plugin-browserskill/skill/references/help-and-recovery.md b/packages/dsh-plugin-browserskill/skill/references/help-and-recovery.md index 921274392..5e39ffd95 100644 --- a/packages/dsh-plugin-browserskill/skill/references/help-and-recovery.md +++ b/packages/dsh-plugin-browserskill/skill/references/help-and-recovery.md @@ -49,3 +49,14 @@ backends to bypass limits. Borrow confirmation still applies. - Unconfirmed fill: read the field. Formatting may satisfy the goal; correct only a remaining difference instead of blindly refilling or requesting help. - Other errors: follow the hint; on unrecoverable failure, report and stop the owned session. + +## Local pairing + +On `pairing_required`, follow the [local setup guide](https://github.com/Tencent/BrowserSkill/blob/main/docs/local-pairing.md) +with the intended daemon environment. Have the user paste the private pairing +link into extension settings and wait for Connected / Verified before retrying +the native session tool. Never include the link in logs or shared reports. +`already_paired` preserves the current connection; replace it only when intended. +`replace_mismatch` needs a normal link for a new profile; revoke an unused old +device separately. Never enable verification skipping to bypass an error. +Independent daemon homes require separate pairings. diff --git a/scripts/check-dsh-package.mjs b/scripts/check-dsh-package.mjs index 30a915290..6e089fbe3 100644 --- a/scripts/check-dsh-package.mjs +++ b/scripts/check-dsh-package.mjs @@ -16,7 +16,7 @@ const temp = mkdtempSync(join(tmpdir(), "bsk-package-")); const cwd = process.cwd(); const disposers = []; try { - const [archive] = JSON.parse( + const packResult = JSON.parse( // The shell launches npm.cmd on Windows. Pass paths through npm's config // environment so spaces and shell metacharacters remain literal path bytes. execSync("npm pack --ignore-scripts --json", { @@ -33,6 +33,9 @@ try { }, }), ); + // npm 12 keys JSON pack results by package name; earlier versions return an array. + const [archive] = Array.isArray(packResult) ? packResult : Object.values(packResult); + assert(typeof archive?.filename === "string", "npm pack did not return an archive"); execFileSync("tar", ["-xzf", join(temp, archive.filename), "-C", temp]); const unpacked = join(temp, "package"); const options = { maxEntryBytes: 4_500, browserTools: DSH_BROWSER_TOOLS };