Skip to content

Commit d6801f2

Browse files
authored
feat(browser): restore driver "extension" via a loopback Chrome extension relay (no remote-debugging prompt) (#100619)
* feat(browser): restore driver "extension" via loopback Chrome extension relay Reintroduces browser profile driver "extension" (removed in 2026.3.22) as a loopback relay that drives the user's signed-in Chrome through an MV3 extension instead of the remote-debugging port. This avoids Chrome's blocking "Allow remote debugging?" prompt, which cannot be clicked when the operator drives OpenClaw from a phone. Automated tabs live in an "OpenClaw" tab group (the consent boundary), mirroring the Codex/Claude-in-Chrome model. - relay bridge synthesizes the CDP browser target surface for Playwright connectOverCDP and forwards session-scoped commands to chrome.debugger - relay server binds loopback only; both sides authenticate with a token derived (HMAC-SHA256) from gateway auth, so the raw credential never reaches Chrome; extension origin + loopback Host checks guard the upgrade - built-in "chrome" profile; distinct relay ports per extension profile; relay reconciles on auth rotation / cdpPort change and prunes removed profiles - doctor + status surface the extension transport; doctor keeps repairing the retired relay endpoint URL on legacy "extension" profiles Refs #53599 * feat(browser): bundle the OpenClaw MV3 Chrome extension Thin MV3 extension (chrome-extension/): a WebSocket client to the loopback relay plus chrome.debugger forwarding and OpenClaw tab-group management. All CDP target synthesis lives server-side in the relay bridge, so the extension stays a dumb transport (the removed 2026.3 extension put that logic in a 1000-line untestable service worker). Popup handles pairing and per-tab share toggle; `openclaw browser extension path|pair` load and pair it. A build copy hook stages it into dist so the load path is stable. Refs #53599 * docs(browser): document the Chrome extension profile Adds docs/tools/chrome-extension for the restored extension driver (install, pair, tab-group consent model, security posture) and wires it into the browser docs profile section and nav. Refs #53599 * feat(browser): make the extension relay work on remote browser nodes Derives the relay auth token from a host-local secret in the credentials dir (created on first use) instead of gateway auth. Each machine that runs a browser — the gateway host and every browser node host — owns its own token, so the extension pairs with whichever machine hosts its Chrome and no gateway credential travels to a node. The node host already runs the shared browser control bootstrap, so this is all that was missing for cross-machine control. Also removes the "relay needs gateway auth before it can start" failure mode: startup and `openclaw browser extension pair` ensure the secret exists. Refs #53599 * fix(browser): harden relay secret creation and satisfy CI lint/typecheck - Make the host-local relay secret creation atomic (O_CREAT|O_EXCL + adopt the winner on EEXIST) so the gateway service and `extension pair` CLI cannot mint divergent tokens on a fresh host (would 401 until restart); credentials dir created mode 0700. (adversarial review finding) - Resolve type-aware oxlint findings across the relay + extension: unknown catch vars, addEventListener over ws.on* in the MV3 worker, void async listeners, drop useless returns/spreads, Object.assign over map-spread, safe ws frame decode (Buffer[]/ArrayBuffer), toSorted. - Add extensionRelayDefaultPort/extensionRelayPorts to remaining test config literals; type the extension relay-core module (.d.ts, excluded from dist); regenerate docs_map. * fix(browser): satisfy OpenGrep security policy on the relay - Hash both operands before timingSafeEqual so token comparison has no length short-circuit (GHSA-jj6q-rrrf-h66h). - Bound the relay WebSocketServer with maxPayload (64 MiB, headroom for CDP screenshots/bodies) against oversized frames (GHSA-vw3h-q6xq-jjm5). - Rewrite the config test env helper to avoid the skill-env-host-injection shape (GHSA-82g8-464f-2mv7); it is a test-only env swap.
1 parent ae6dc52 commit d6801f2

52 files changed

Lines changed: 3231 additions & 45 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,7 @@
13521352
"group": "Web browser",
13531353
"pages": [
13541354
"tools/browser",
1355+
"tools/chrome-extension",
13551356
"tools/browser-control",
13561357
"tools/browser-login",
13571358
"tools/browser-linux-troubleshooting",

docs/docs_map.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8985,7 +8985,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
89858985
- H2: Plugin control
89868986
- H2: Agent guidance
89878987
- H2: Missing browser command or tool
8988-
- H2: Profiles: openclaw vs user
8988+
- H2: Profiles: openclaw, user, chrome
89898989
- H2: Configuration
89908990
- H3: Screenshot vision (text-only model support)
89918991
- H2: Use Brave or another Chromium-based browser
@@ -9025,6 +9025,18 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
90259025
- Headings:
90269026
- H2: Related
90279027

9028+
## tools/chrome-extension.md
9029+
9030+
- Route: /tools/chrome-extension
9031+
- Headings:
9032+
- H1: Chrome extension
9033+
- H2: How it works
9034+
- H2: Install and pair
9035+
- H2: Use it
9036+
- H2: Remote browser nodes
9037+
- H2: Diagnostics
9038+
- H2: Security model
9039+
90289040
## tools/clawhub.md
90299041

90309042
- Route: /tools/clawhub

docs/tools/browser.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,24 @@ channel config behavior. `plugins.entries.browser.enabled=true` and
118118
`tools.alsoAllow: ["browser"]` do not substitute for allowlist membership by
119119
themselves. Removing `plugins.allow` entirely also restores the default.
120120

121-
## Profiles: `openclaw` vs `user`
121+
## Profiles: `openclaw`, `user`, `chrome`
122122

123123
- `openclaw`: managed, isolated browser (no extension required).
124124
- `user`: built-in Chrome DevTools MCP attach profile for your **real
125-
signed-in Chrome** session.
125+
signed-in Chrome** session. Chrome shows a blocking "Allow remote debugging?"
126+
prompt the first time OpenClaw attaches, so someone must be at the computer.
127+
- `chrome`: built-in [Chrome extension](/tools/chrome-extension) profile for
128+
your **real signed-in Chrome** session. Works from a phone with nobody at the
129+
desk because it drives tabs through the OpenClaw browser extension instead of
130+
the remote-debugging port, so there is no "Allow remote debugging?" prompt.
126131

127132
For agent browser tool calls:
128133

129134
- Default: use the isolated `openclaw` browser.
130-
- Prefer `profile="user"` when existing logged-in sessions matter and the user
131-
is at the computer to click/approve any attach prompt.
135+
- Prefer `profile="chrome"` (extension) when existing logged-in sessions matter
136+
and the user is **away from the computer** (Telegram, WhatsApp, etc.).
137+
- Prefer `profile="user"` (Chrome MCP) when existing logged-in sessions matter
138+
and the user is **at the computer** to approve the attach prompt.
132139
- `profile` is the explicit override when you want a specific browser mode.
133140

134141
Set `browser.defaultProfile: "openclaw"` if you want managed mode by default.
@@ -310,6 +317,7 @@ main model can read the screenshot directly.
310317
- Default profile is `openclaw` (managed standalone). Use `defaultProfile: "user"` to opt into the signed-in user browser.
311318
- Auto-detect order: system default browser if Chromium-based; otherwise Chrome, Brave, Edge, Chromium, Chrome Canary.
312319
- `driver: "existing-session"` uses Chrome DevTools MCP instead of raw CDP. It can attach through Chrome MCP auto-connect, or through `cdpUrl` when you already have a DevTools endpoint for the running browser.
320+
- `driver: "extension"` drives your signed-in Chrome through the [OpenClaw Chrome extension](/tools/chrome-extension). The relay owns its loopback endpoint, so these profiles do not accept `cdpUrl`. This is the only signed-in-browser mode that works with nobody at the computer.
313321
- Set `browser.profiles.<name>.userDataDir` when an existing-session profile should attach to a non-default Chromium user profile (Brave, Edge, etc.). This path also accepts `~` for your OS home directory.
314322

315323
</Accordion>

docs/tools/chrome-extension.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
---
2+
summary: "Chrome extension: let OpenClaw drive your signed-in Chrome with no remote-debugging prompt"
3+
read_when:
4+
- You want an agent to drive your real signed-in Chrome from your phone
5+
- You keep hitting the Chrome "Allow remote debugging?" prompt with nobody at the desk
6+
- You want to understand the security model of browser takeover via the extension
7+
title: "Chrome Extension"
8+
---
9+
10+
# Chrome extension
11+
12+
The OpenClaw Chrome extension lets an agent control your **signed-in Chrome
13+
tabs** without launching a separate managed browser, and **without** Chrome's
14+
blocking "Allow remote debugging?" prompt.
15+
16+
This matters when you drive OpenClaw from a phone (Telegram, WhatsApp, etc.):
17+
the [`user` profile](/tools/browser#profiles-openclaw-user-chrome) attaches over
18+
Chrome's remote-debugging port, which pops a desktop consent dialog nobody can
19+
click when you are away. The extension uses the `chrome.debugger` API instead,
20+
so the only in-page hint is Chrome's dismissible "OpenClaw started debugging
21+
this browser" banner.
22+
23+
This is the same shape used by Anthropic's Claude in Chrome and OpenAI's Codex
24+
Chrome extensions.
25+
26+
## How it works
27+
28+
Three parts:
29+
30+
- **Browser control service** (Gateway or node host): the API the `browser`
31+
tool calls.
32+
- **Extension relay** (loopback WebSocket): a small server the control service
33+
starts on `127.0.0.1`. It presents a Chrome DevTools Protocol endpoint to
34+
OpenClaw and speaks to the extension. Both sides authenticate with a
35+
host-local token (see below).
36+
- **OpenClaw Chrome extension** (MV3): attaches to tabs with `chrome.debugger`,
37+
forwards CDP traffic, and manages the **OpenClaw tab group**.
38+
39+
OpenClaw only sees and controls tabs that are in the **OpenClaw tab group**. The
40+
group is the consent boundary: drag a tab in to share it, drag it out (or click
41+
the toolbar button) to revoke access instantly.
42+
43+
## Install and pair
44+
45+
1. Print the unpacked extension path:
46+
47+
```bash
48+
openclaw browser extension path
49+
```
50+
51+
2. Open `chrome://extensions`, enable **Developer mode**, click **Load
52+
unpacked**, and select the printed directory.
53+
54+
3. Print the pairing string:
55+
56+
```bash
57+
openclaw browser extension pair
58+
```
59+
60+
4. Click the OpenClaw toolbar icon and paste the pairing string into the popup.
61+
The badge turns **ON** when the extension connects to the relay.
62+
63+
The pairing token is a **host-local secret** created on first use and stored
64+
under `credentials/` in the state directory (mode `0600`). Each machine that
65+
runs a browser — the Gateway host and every browser node host — owns its own
66+
token, so no credential has to travel between machines. To rotate it, delete the
67+
`browser-extension-relay.secret` file and pair again.
68+
69+
## Use it
70+
71+
Select the built-in `chrome` profile in a `browser` tool call, or make it the
72+
default:
73+
74+
```bash
75+
openclaw config set browser.defaultProfile chrome
76+
```
77+
78+
```json5
79+
{
80+
browser: {
81+
profiles: {
82+
chrome: { driver: "extension", color: "#FF4500" },
83+
},
84+
},
85+
}
86+
```
87+
88+
- Share a tab: click the OpenClaw toolbar button on that tab (it joins the
89+
OpenClaw tab group), or drag any tab into the group.
90+
- The agent can also open new tabs; those land in the group automatically.
91+
- Revoke: click the button again, drag the tab out of the group, or dismiss
92+
Chrome's debugging banner. The agent loses access to that tab immediately.
93+
94+
## Remote browser nodes
95+
96+
The extension works whether Chrome runs on the Gateway host or on a separate
97+
[browser node host](/tools/browser#local-vs-remote-control). The relay is always
98+
loopback-only and runs **on the machine with the browser**:
99+
100+
- **Same host** (Gateway + Chrome on one machine): pair on that machine.
101+
- **Remote node** (Chrome on a node, Gateway elsewhere): run
102+
`openclaw browser extension path` / `pair` **on the node**, load and pair the
103+
extension there. The Gateway proxies browser actions to the node over its
104+
existing authenticated node link; the node's local relay drives the extension.
105+
No new inbound port is opened on the node.
106+
107+
The pairing token is per host, so each node prints its own string.
108+
109+
## Diagnostics
110+
111+
```bash
112+
openclaw browser status --browser-profile chrome
113+
openclaw browser doctor --browser-profile chrome
114+
```
115+
116+
`doctor` reports the **Chrome extension relay** check as failing until the
117+
extension popup shows **Connected**.
118+
119+
## Security model
120+
121+
- The relay binds loopback only; both WebSocket sides are authenticated with the
122+
derived token, and the extension side is origin-checked to `chrome-extension://`.
123+
- The agent can only see and drive tabs in the **OpenClaw tab group**. Your
124+
other tabs stay private.
125+
- Compared with the `user` (Chrome MCP) profile, which exposes your whole
126+
signed-in browser once you approve the remote-debugging prompt, the extension
127+
keeps the shared surface scoped to a tab group you control at a glance.
128+
129+
See also: [Browser](/tools/browser) for the full profile model and the
130+
managed `openclaw` and Chrome MCP `user` profiles.

0 commit comments

Comments
 (0)