Skip to content

fix(sandbox): require auth token for browser bridge server#11027

Closed
coygeek wants to merge 1 commit intoopenclaw:mainfrom
coygeek:fix/aa04-sandbox-browser-auth
Closed

fix(sandbox): require auth token for browser bridge server#11027
coygeek wants to merge 1 commit intoopenclaw:mainfrom
coygeek:fix/aa04-sandbox-browser-auth

Conversation

@coygeek
Copy link
Copy Markdown
Contributor

@coygeek coygeek commented Feb 7, 2026

Fix Summary

Generate a cryptographically random auth token when starting the sandbox browser bridge and pass it to startBrowserBridgeServer(). This ensures all bridge endpoints require Bearer token authentication, preventing cross-session local takeover of sandbox browser state.

Previously, the sandbox startup path called startBrowserBridgeServer() without an authToken, leaving the bridge API completely unauthenticated to any local process.

Issue Linkage

Fixes #11023

Security Snapshot

Metric Value
Score 9.2 / 10.0
Severity Critical
Vector CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:L

Implementation Details

Files Changed

  • src/agents/sandbox/browser-bridges.ts (+4/-1)
  • src/agents/sandbox/browser.ts (+19/-7)
  • src/agents/sandbox/types.ts (+1/-0)
  • src/browser/client-fetch.ts (+38/-1)

Technical Analysis

Generate a cryptographically random auth token when starting the sandbox browser bridge and pass it to startBrowserBridgeServer(). This ensures all bridge endpoints require Bearer token authentication, preventing cross-session local takeover of sandbox browser state.

Validation Evidence

  • Command: pnpm build
  • Status: passed

Risk and Compatibility

non-breaking; compatibility impact was not explicitly documented in the original PR body.

AI-Assisted Disclosure

  • AI-assisted: yes
  • Model: Claude Code

Greptile Overview

Greptile Summary

  • Sandbox browser startup now generates a per-bridge auth token and passes it to startBrowserBridgeServer() so the local bridge API enforces Bearer authentication.
  • Sandbox browser context and bridge registry are extended to store/return the token alongside the bridge base URL.
  • Browser HTTP client code adds a registry keyed by bridge base URL to automatically attach Authorization: Bearer <token> to bridge requests.

Confidence Score: 4/5

  • Mostly safe to merge, but one header-merging bug can break authenticated bridge requests for some callers.
  • Core change (generating/passing auth tokens and registering them for bridge requests) is straightforward and scoped. The main concern is fetchBrowserJson’s new header merge logic: it assumes init.headers is a plain object, which is not guaranteed by Fetch and can cause Authorization injection to be dropped, leading to 401s at runtime depending on how callers construct headers.
  • src/browser/client-fetch.ts

Generate a cryptographically random auth token when starting the sandbox
browser bridge and pass it to startBrowserBridgeServer(). This ensures
all bridge endpoints require Bearer token authentication, preventing
cross-session local takeover of sandbox browser state.

The token is registered in a URL-keyed registry so that fetchBrowserJson
transparently attaches the Authorization header to all outgoing HTTP
requests targeting the protected bridge. The token is also exposed via
SandboxBrowserContext.bridgeAuthToken for the owning session.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle bot added the agents Agent runtime and tooling label Feb 7, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +91 to 96
const mergedHeaders = {
...authHeaders,
...(init?.headers as Record<string, string> | undefined),
};
return await fetchHttpJson<T>(url, { ...init, headers: mergedHeaders, timeoutMs });
}
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.

Bearer auth header lost

fetchBrowserJson() merges headers with { ...authHeaders, ...(init?.headers as Record<string, string> | undefined) }, but RequestInit.headers is not always a plain object (it can be Headers or [string, string][]). Spreading a Headers instance produces {} in practice, so callers that pass new Headers(...) will silently drop both their own headers and the injected Authorization header, causing sandbox bridge requests to fail with 401.

Consider normalizing via new Headers(init?.headers) and then set("Authorization", ...) before calling fetchHttpJson.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/browser/client-fetch.ts
Line: 91:96

Comment:
**Bearer auth header lost**

`fetchBrowserJson()` merges headers with `{ ...authHeaders, ...(init?.headers as Record<string, string> | undefined) }`, but `RequestInit.headers` is not always a plain object (it can be `Headers` or `[string, string][]`). Spreading a `Headers` instance produces `{}` in practice, so callers that pass `new Headers(...)` will silently drop both their own headers *and* the injected `Authorization` header, causing sandbox bridge requests to fail with 401.

Consider normalizing via `new Headers(init?.headers)` and then `set("Authorization", ...)` before calling `fetchHttpJson`.

How can I resolve this? If you propose a fix, please make it concise.

@leszekszpunar
Copy link
Copy Markdown
Contributor

Heads up: the lint failure (preserve-caught-error in extensions/memory-lancedb/index.ts) is a pre-existing issue on main, not caused by your changes. The fix is in #11061. Once it lands, rebase on main and re-push to get a clean CI run.

git fetch origin main && git rebase origin/main && git push --force-with-lease

@leszekszpunar
Copy link
Copy Markdown
Contributor

Update: the lint failure has been resolved by #11093 (merged), which excluded extensions/ from oxlint scope. A rebase on main should give you a clean CI run.

git fetch origin main && git rebase origin/main && git push --force-with-lease

@coygeek
Copy link
Copy Markdown
Contributor Author

coygeek commented Feb 16, 2026

Cleanup note for traceability:

  • Linked issue #11023 was closed by maintainer as duplicate of #6609.
  • Keeping discussion/work tracking under canonical issue #6609 (linked issue closed as duplicate).

Closing this PR to align with duplicate routing. If maintainers want this exact patch revived, I can reopen or submit a retargeted PR.

@coygeek coygeek closed this Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Sandbox browser bridge is started without auth token, allowing cross-session local takeover

2 participants