#16060: fix(browser): require relay auth token for /extension WebSocket and /extension/status
stale
size: XS
trusted-contributor
Cluster:
Chrome Extension Enhancements
## Fix Summary
Require the existing `relayAuthToken` for `/extension` WebSocket connections and `/extension/status` HTTP endpoint, matching the security model already enforced for `/cdp`.
## Issue Linkage
Fixes #16059
## Security Snapshot
- CVSS v3.1: 8.1 (High)
- CVSS v4.0: 8.8 (High)
## Implementation Details
### Files Changed
- `src/browser/extension-relay.ts` (+11/-0) — Add token auth checks to `/extension` WS upgrade and `/extension/status` HTTP handler
- `src/browser/extension-relay.test.ts` (+22/-3) — Update existing tests to pass auth headers; add regression test for unauthenticated rejection
### Technical Analysis
The `/extension` WebSocket endpoint accepted connections authenticated only by a loopback address check and a bypassable Origin header check. The `/cdp` endpoint on the same server already required a cryptographic `relayAuthToken` via the `x-openclaw-relay-token` header. This fix extends the same token check to both the `/extension` WebSocket upgrade path and the `/extension/status` HTTP endpoint, closing the authentication gap that allowed local processes to impersonate the Chrome extension.
## Validation Evidence
- Command: `pnpm build && pnpm check && npx vitest run src/browser/extension-relay.test.ts`
- Status: all passed (5/5 tests, 0 lint warnings, 0 errors)
## Risk and Compatibility
Non-breaking for the Chrome extension — it already receives the relay auth token via `getChromeExtensionRelayAuthHeaders()` and can pass it for `/extension` connections. Only unauthenticated local processes are blocked.
## AI-Assisted Disclosure
- AI-assisted: yes
- Model: Claude Opus 4.6
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR extends relay auth token checks to the `/extension` WebSocket upgrade and `/extension/status` HTTP endpoints, matching the existing pattern enforced for `/cdp`. While the security intent is sound, there is a critical compatibility issue: the Chrome extension (`assets/chrome-extension/background.js`) connects to `/extension` using the browser's native `WebSocket` API, which **does not support custom HTTP headers**. The extension currently uses `new WebSocket(wsUrl)` with no auth token. This means the new auth check will reject all real Chrome extension connections.
- The `/cdp` endpoint's auth works because it is connected to by server-side Node.js code (via `cdp.helpers.ts` / `ws` library), which does support custom headers
- The `/extension` endpoint is connected to by a Chrome extension service worker running in the browser, where `WebSocket` only accepts a URL and optional sub-protocols
- The PR description's claim that "the extension already receives the relay auth token via `getChromeExtensionRelayAuthHeaders()`" is incorrect — that function is server-side Node.js code, not accessible from the browser extension
- The tests pass because they use the Node.js `ws` library (which supports headers), not the browser `WebSocket` API
- An alternative auth mechanism is needed for the extension path (e.g., query parameter token, sub-protocol, or HTTP-based token exchange)
<h3>Confidence Score: 1/5</h3>
- This PR will break the Chrome extension's ability to connect to the relay server in production.
- The auth mechanism (custom HTTP header on WebSocket upgrade) is incompatible with the browser WebSocket API used by the Chrome extension. While the Node.js-based tests pass, real extension connections will be rejected with 401. The security goal is valid but the implementation needs an auth mechanism that works from browser contexts.
- Pay close attention to `src/browser/extension-relay.ts` (lines 476-481) and `assets/chrome-extension/background.js` (line 68) — the auth mechanism is incompatible with the browser WebSocket API.
<sub>Last reviewed commit: 4eab139</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20688: fix(browser): allow extension reconnect when stale websocket linger...
by HOYALIM · 2026-02-19
79.4%
#5278: fix(browser): prevent DNS rebinding in extension relay HTTP endpoints
by webvijayi · 2026-01-31
79.1%
#22571: fix(browser): complete extension relay handshake on connect.challenge
by pandego · 2026-02-21
77.9%
#17588: fix(relay): survive WS disconnects and MV3 worker restarts
by Unayung · 2026-02-15
77.3%
#6000: fix(browser): add CORS headers for chrome-extension:// origins
by lailoo · 2026-02-01
76.8%
#16689: browser: support multiple Chrome extension connections to relay
by globalcaos · 2026-02-15
76.4%
#21314: feat: enhance browser relay with custom naming and diagnostic tools
by kelvinCB · 2026-02-19
76.2%
#14197: fix(security): harden browser API auth, token comparisons, and hook...
by leecarollyn-gif · 2026-02-11
75.1%
#19766: fix: Chrome relay extension auto-reattach after SPA navigation
by nishantkabra77 · 2026-02-18
75.1%
#22252: fix(chrome-extension): connection validation and clarify relay port...
by krizpoon · 2026-02-20
74.6%