Skip to content

fix(browser): tighten strict browser hostname navigation#64367

Merged
drobison00 merged 4 commits into
openclaw:mainfrom
eleqtrizit:browser-ssrf-guard
Apr 10, 2026
Merged

fix(browser): tighten strict browser hostname navigation#64367
drobison00 merged 4 commits into
openclaw:mainfrom
eleqtrizit:browser-ssrf-guard

Conversation

@eleqtrizit

Copy link
Copy Markdown
Contributor

Summary

  • tighten strict browser navigation so hostname-based URLs do not proceed when Chromium would re-resolve DNS outside the Node-side SSRF checks
  • route strict CDP HTTP discovery through the pinned SSRF fetch path

Changes

  • reject strict-policy hostname navigation unless the hostname is an explicit operator allowlist exception or an IP literal
  • pass browser CDP /json/version requests through fetchWithSsrFGuard when an SSRF policy is active
  • add regression coverage for strict hostname navigation denial in the browser navigation, CDP, and Playwright navigation tests

Validation

  • Ran corepack pnpm test extensions/browser/src/browser/navigation-guard.test.ts extensions/browser/src/browser/cdp.test.ts extensions/browser/src/browser/pw-session.create-page.navigation-guard.test.ts
  • Ran corepack pnpm check
  • Attempted local agentic review with claude -p "/review", but the command timed out without output

Notes

  • This is a holding fix: strict hostname-based browser navigation now fails closed unless the hostname is explicitly allowlisted
  • CDP WebSocket attachment remains operator-configured surface area; the patch hardens the HTTP discovery path without changing remote browser attachment contracts

@openclaw-barnacle openclaw-barnacle Bot added size: S maintainer Maintainer-authored PR labels Apr 10, 2026
@greptile-apps

greptile-apps Bot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR tightens browser SSRF protections in two ways: (1) hostname-based URLs are blocked in strict mode unless the hostname is an IP literal or explicitly operator-allowlisted (because Chromium's network stack re-resolves DNS independently from Node's SSRF checks), and (2) CDP HTTP discovery requests (/json/version, /json/list, etc.) are now routed through fetchWithSsrFGuard when an SSRF policy is active. The release-ordering bug flagged in the previous round is resolved — release() is now called after the response body is fully consumed, verified by the new cdp.helpers.test.ts fixture.

Confidence Score: 5/5

Safe to merge — no P0/P1 issues found; previous release-ordering bug is resolved and the strict hostname gate is well-tested.

All remaining findings are P2 (minor inline normalization vs shared helper). The two previously flagged blocking issues (release() ordering and the agent work-log file) are both resolved in this revision. Comprehensive regression tests cover the new strict-mode paths.

No files require special attention.

Reviews (2): Last reviewed commit: "fix(browser): address review follow-ups" | Re-trigger Greptile

Comment thread extensions/browser/src/browser/cdp.helpers.ts Outdated
Comment thread USER.md Outdated
Comment thread extensions/browser/src/browser/navigation-guard.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: abbad83bc8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread extensions/browser/src/browser/navigation-guard.ts Outdated
@eleqtrizit

Copy link
Copy Markdown
Contributor Author

@codex review

@eleqtrizit

Copy link
Copy Markdown
Contributor Author

@greptile review

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

Codex Review: Didn't find any major issues. Delightful!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.
@drobison00
drobison00 merged commit 121c452 into openclaw:main Apr 10, 2026
8 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e78000ad1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

cdpUrl: profile.cdpUrl,
ssrfPolicy: state().resolved.ssrfPolicy,
});
const pages = await listPagesViaPlaywright({ cdpUrl: profile.cdpUrl });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Propagate SSRF policy to Playwright listTabs calls

This call now invokes listPagesViaPlaywright without ssrfPolicy, and the pre-check assertCdpEndpointAllowed was also removed in this function. In strict mode, that means connectBrowser receives undefined policy and skips endpoint SSRF validation on cache miss, so a blocked cdpUrl can still be connected and cached before any guard runs. This is a security regression for remote profiles that use persistent Playwright tab listing.

Useful? React with 👍 / 👎.

Comment on lines 112 to 115
await focusPageByTargetIdViaPlaywright({
cdpUrl: profile.cdpUrl,
targetId: resolvedTargetId,
ssrfPolicy: state().resolved.ssrfPolicy,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Propagate SSRF policy to Playwright focus/close calls

The Playwright focus/close path now omits ssrfPolicy when calling focusPageByTargetIdViaPlaywright (and similarly closePageByTargetIdViaPlaywright below), while endpoint pre-checks were removed from this file. Because Playwright session attachment enforces endpoint SSRF policy only when connectBrowser is called with a policy on cache miss, these operations can bypass strict cdpUrl blocking for remote profiles.

Useful? React with 👍 / 👎.

Comment on lines +66 to +68
await resolvePinnedHostnameWithPolicy(parsed.hostname, {
policy: ssrfPolicy,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rewrap endpoint SSRF failures as endpoint-scoped errors

Removing the SsrFBlockedError -> BrowserCdpEndpointBlockedError conversion here changes error classification for blocked CDP endpoints. toBrowserErrorResponse still treats raw SsrFBlockedError as a navigation-target failure, so strict-policy endpoint denials are now reported as navigation blocks instead of endpoint configuration blocks, which breaks the existing endpoint-vs-navigation error contract.

Useful? React with 👍 / 👎.

lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
)

* fix(browser): tighten strict browser hostname navigation

* fix(browser): address review follow-ups

* chore(changelog): add strict browser hostname navigation entry

* fix(browser): remove stale state prop from SelectionDeps call site

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.

---------

Co-authored-by: Devin Robison <[email protected]>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
)

* fix(browser): tighten strict browser hostname navigation

* fix(browser): address review follow-ups

* chore(changelog): add strict browser hostname navigation entry

* fix(browser): remove stale state prop from SelectionDeps call site

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.

---------

Co-authored-by: Devin Robison <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
)

* fix(browser): tighten strict browser hostname navigation

* fix(browser): address review follow-ups

* chore(changelog): add strict browser hostname navigation entry

* fix(browser): remove stale state prop from SelectionDeps call site

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.

---------

Co-authored-by: Devin Robison <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
)

* fix(browser): tighten strict browser hostname navigation

* fix(browser): address review follow-ups

* chore(changelog): add strict browser hostname navigation entry

* fix(browser): remove stale state prop from SelectionDeps call site

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.

---------

Co-authored-by: Devin Robison <[email protected]>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
)

* fix(browser): tighten strict browser hostname navigation

* fix(browser): address review follow-ups

* chore(changelog): add strict browser hostname navigation entry

* fix(browser): remove stale state prop from SelectionDeps call site

The PR's SelectionDeps uses getSsrFPolicy instead of the full state
object; the state property was leftover from an earlier iteration.

---------

Co-authored-by: Devin Robison <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants