openclaw - ✅(Solved) Fix [Bug]: Remote CDP `status` / `tabs` false-negative when `browser.ssrfPolicy` is unset because the no-config resolver returns `{}` [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#68108Fetched 2026-04-18 05:53:53
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×2commented ×1cross-referenced ×1

In a WSL OpenClaw -> Windows Chrome remote CDP setup, openclaw browser status and openclaw browser tabs can false-negative even though the remote CDP endpoint is healthy.

Validated setup:

  • browser.defaultProfile=remote
  • cdpUrl=http://172.29.128.1:9223
  • attach-only remote CDP
  • no explicit browser.ssrfPolicy configured

Observed behavior:

  • openclaw browser status reports running: false
  • openclaw browser tabs returns empty / No tabs (browser closed or no targets).

At the same time:

  • raw GET /json/version succeeds
  • raw GET /json/list shows many live page targets
  • Playwright connectOverCDP() succeeds
  • direct websocket health (Browser.getVersion) succeeds

Validated root cause: browser.ssrfPolicy unset currently resolves to {} instead of undefined / null, and that empty object is still treated as an active SSRF policy in the strict CDP readiness path.

Root Cause

Validated root cause: browser.ssrfPolicy unset currently resolves to {} instead of undefined / null, and that empty object is still treated as an active SSRF policy in the strict CDP readiness path.

Fix Action

Fix / Workaround

Debug instrumentation was later rolled back. Only the functional resolver patch was kept during validation.

PR fix notes

PR #68207: Fix: auto-allowlist configured CDP hostnames in SSRF policy (Resolves #68108)

Description (problem / solution / changelog)

Fixes #68108.

Problem

When browser.ssrfPolicy is unset, resolveBrowserSsrFPolicy returns a fail-closed default policy ({}). That default blocks any user-configured remote CDP endpoint on a private-network host (e.g. WSL → Windows Chrome at http://172.29.128.1:9223), because assertCdpEndpointAllowed routes through resolvePinnedHostnameWithPolicy, which blocks private IPs unless they appear in allowedHostnames or dangerouslyAllowPrivateNetwork is explicitly set.

Symptoms:

  • openclaw browser statusrunning: false
  • openclaw browser tabs → empty

…even though raw /json/version, Playwright connectOverCDP(), and the CDP websocket are all healthy.

Fix

Auto-allowlist every hostname that the user explicitly configured via browser.cdpUrl or browser.profiles.*.cdpUrl by merging them into ssrfPolicy.allowedHostnames inside resolveBrowserConfig. This mirrors the existing loopback auto-allowlist in assertCdpEndpointAllowed: explicit user configuration is trusted, while the fail-closed default still applies to arbitrary URLs.

  • resolveBrowserSsrFPolicy accepts an optional extraAllowedHostnames list and merges it into allowedHostnames (deduped).
  • New helper collectConfiguredCdpHostnames pulls hostnames from cfg.cdpUrl and each cfg.profiles.*.cdpUrl, skipping unparseable URLs.

Tests

  • Added three new cases to extensions/browser/src/browser/config.test.ts covering: no ssrfPolicy + configured profile cdpUrl, merging with existing allowedHostnames, and dedupe.
  • All 579 existing browser tests still pass (pnpm test extensions/browser/src/browser/).

Changed files

  • extensions/browser/src/browser/config.test.ts (modified, +46/-0)
  • extensions/browser/src/browser/config.ts (modified, +43/-3)

Code Example

Available evidence from local validation:
- raw `GET /json/version` succeeded
- raw `GET /json/list` showed many live `type=page` targets
- Playwright `connectOverCDP()` succeeded and enumerated pages
- direct websocket connect + `Browser.getVersion` succeeded
- exact failing chain was confirmed during local runtime instrumentation

Validated minimal local fix:
- in `config-C4Yha3Le.js`
- change the no-config case in `resolveBrowserSsrFPolicy(cfg)`
- from `return {}`
- to `return undefined` (or `null`)

After restarting the gateway:
- `openclaw browser status` changed to `running: true`
- `openclaw browser tabs` returned the normal live tab list

Debug instrumentation was later rolled back. Only the functional resolver patch was kept during validation.
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

In a WSL OpenClaw -> Windows Chrome remote CDP setup, openclaw browser status and openclaw browser tabs can false-negative even though the remote CDP endpoint is healthy.

Validated setup:

  • browser.defaultProfile=remote
  • cdpUrl=http://172.29.128.1:9223
  • attach-only remote CDP
  • no explicit browser.ssrfPolicy configured

Observed behavior:

  • openclaw browser status reports running: false
  • openclaw browser tabs returns empty / No tabs (browser closed or no targets).

At the same time:

  • raw GET /json/version succeeds
  • raw GET /json/list shows many live page targets
  • Playwright connectOverCDP() succeeds
  • direct websocket health (Browser.getVersion) succeeds

Validated root cause: browser.ssrfPolicy unset currently resolves to {} instead of undefined / null, and that empty object is still treated as an active SSRF policy in the strict CDP readiness path.

Steps to reproduce

  1. Run OpenClaw in WSL.
  2. Run Windows Chrome with remote debugging enabled.
  3. Configure OpenClaw browser integration to use:
    • browser.defaultProfile=remote
    • cdpUrl=http://172.29.128.1:9223
  4. Leave browser.ssrfPolicy unset.
  5. Make sure Chrome already has normal live tabs open.
  6. From WSL, verify:
    • http://172.29.128.1:9223/json/version
    • http://172.29.128.1:9223/json/list
  7. Run:
    • openclaw browser status
    • openclaw browser tabs

Optional confirmation: 8. Attach with Playwright via connectOverCDP() and verify pages can be enumerated.

Expected behavior

If browser.ssrfPolicy is not configured, the remote CDP readiness path should not behave as if an SSRF policy is active.

For a healthy configured endpoint like http://172.29.128.1:9223, OpenClaw should report:

  • running: true
  • normal live tabs

Actual behavior

OpenClaw reports:

  • openclaw browser status -> running: false
  • openclaw browser tabs -> empty / No tabs (browser closed or no targets).

But the endpoint is actually healthy:

  • raw /json/version succeeds
  • raw /json/list returns many live page targets
  • Playwright connectOverCDP() succeeds
  • direct websocket Browser.getVersion succeeds

Confirmed failing chain:

  • status / tabs
  • -> profileCtx.isReachable(...)
  • -> isChromeCdpReady(...)
  • -> getChromeWebSocketUrl(...)
  • -> assertCdpEndpointAllowed(cdpUrl, ssrfPolicy)
  • -> BrowserCdpEndpointBlockedError: browser endpoint blocked by policy

Confirmed config/guard mismatch:

  • resolveBrowserSsrFPolicy(cfg) returns {} when browser.ssrfPolicy is unset
  • assertCdpEndpointAllowed(cdpUrl, ssrfPolicy) only skips checks when !ssrfPolicy

Because {} is truthy, the strict remote CDP readiness path still applies endpoint SSRF validation to the configured private bridge endpoint.

OpenClaw version

2026.4.11

Operating system

OpenClaw host: WSL on Windows Remote browser host: Windows Chrome via remote debugging

Install method

npm global install

Model

Not model-specific. This appears to be in browser/CDP readiness logic, not model execution.

Provider / routing chain

Not provider/model routing related. Relevant runtime path: WSL OpenClaw -> Windows Chrome remote CDP

Additional provider/model setup details

None. This issue appears independent of model/provider configuration.

Logs, screenshots, and evidence

Available evidence from local validation:
- raw `GET /json/version` succeeded
- raw `GET /json/list` showed many live `type=page` targets
- Playwright `connectOverCDP()` succeeded and enumerated pages
- direct websocket connect + `Browser.getVersion` succeeded
- exact failing chain was confirmed during local runtime instrumentation

Validated minimal local fix:
- in `config-C4Yha3Le.js`
- change the no-config case in `resolveBrowserSsrFPolicy(cfg)`
- from `return {}`
- to `return undefined` (or `null`)

After restarting the gateway:
- `openclaw browser status` changed to `running: true`
- `openclaw browser tabs` returned the normal live tab list

Debug instrumentation was later rolled back. Only the functional resolver patch was kept during validation.

Impact and severity

Medium to high for remote-CDP users.

This can make a healthy remote browser integration appear broken, because:

  • status reports running: false
  • tabs returns empty
  • users may assume the remote Chrome target or OpenClaw browser integration is fundamentally broken

The bug is especially misleading because raw CDP, Playwright, and websocket health can all be healthy at the same time.

Additional information

Suggested upstream fix:

Preferred:

  • make resolveBrowserSsrFPolicy() return undefined or null when browser SSRF policy is unset

Alternative:

  • make CDP endpoint guards treat an empty policy object as disabled

I think the first option is cleaner because it preserves the meaning of “no browser SSRF policy configured”.

I have a minimal local fix validated and can open a PR if this direction looks right.

extent analysis

TL;DR

The most likely fix is to modify the resolveBrowserSsrFPolicy() function to return undefined or null when the browser SSRF policy is unset, instead of an empty object.

Guidance

  • The issue is caused by the resolveBrowserSsrFPolicy() function returning an empty object ({}) when the browser SSRF policy is unset, which is still treated as an active SSRF policy in the strict CDP readiness path.
  • To fix this, the resolveBrowserSsrFPolicy() function should be modified to return undefined or null when the browser SSRF policy is unset.
  • The fix can be verified by checking if openclaw browser status reports running: true and openclaw browser tabs returns the normal live tab list after applying the patch.
  • An alternative solution is to make CDP endpoint guards treat an empty policy object as disabled, but the preferred solution is to modify the resolveBrowserSsrFPolicy() function.

Example

// Modified resolveBrowserSsrFPolicy() function
function resolveBrowserSsrFPolicy(cfg) {
  // ...
  if (!cfg.browser.ssrfPolicy) {
    return undefined; // or return null;
  }
  // ...
}

Notes

  • The issue is specific to the OpenClaw version 2026.4.11 and may not apply to other versions.
  • The fix is independent of model/provider configuration.

Recommendation

Apply the workaround by modifying the resolveBrowserSsrFPolicy() function to return undefined or null when the browser SSRF policy is unset, as this is the preferred solution.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

If browser.ssrfPolicy is not configured, the remote CDP readiness path should not behave as if an SSRF policy is active.

For a healthy configured endpoint like http://172.29.128.1:9223, OpenClaw should report:

  • running: true
  • normal live tabs

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Remote CDP `status` / `tabs` false-negative when `browser.ssrfPolicy` is unset because the no-config resolver returns `{}` [1 pull requests, 1 comments, 2 participants]