Skip to content

feat(browser): add cookies action for retrieving browser cookies including HttpOnly#7635

Closed
euisuk-chung wants to merge 3 commits into
openclaw:mainfrom
euisuk-chung:feat/browser-cookies-action
Closed

feat(browser): add cookies action for retrieving browser cookies including HttpOnly#7635
euisuk-chung wants to merge 3 commits into
openclaw:mainfrom
euisuk-chung:feat/browser-cookies-action

Conversation

@euisuk-chung

@euisuk-chung euisuk-chung commented Feb 3, 2026

Copy link
Copy Markdown

Summary

Add a new cookies action to the browser tool that allows retrieving browser cookies including
HttpOnly cookies via Playwright CDP.

  • New action: browser action="cookies" to retrieve cookies from browser context
  • Domain filtering: Optional domain parameter to filter cookies by domain
  • Proxy support: Works with both local browser control and Node Host proxy routing
  • HttpOnly access: Can retrieve HttpOnly cookies via CDP (not accessible via JavaScript)

Use Case

Enable MCP server authentication token refresh by extracting session cookies from authenticated
browser sessions. For example, NotebookLM MCP authentication requires Google session cookies (HSID,
SSID, SID) which are HttpOnly and cannot be accessed via document.cookie.

Usage

browser action="cookies" profile="chrome" domain="google.com"

Returns:

{
"ok": true,
"targetId": "ABC123",
"cookies": [
  {
    "name": "SID",
    "value": "...",
    "domain": ".google.com",
    "path": "/",
    "httpOnly": true,
    "secure": true,
    "sameSite": "Lax"
  }
]
}

Test plan

- Unit tests added for cookies action
- Tests for domain filtering
- Tests for Node Host proxy routing
- All existing browser-tool tests pass

euisuk-chung and others added 2 commits February 2, 2026 22:36
…elay

The Chrome extension relay server needs to be running before the
extension can connect. Previously, the browser control service was
initialized lazily (on first browser.proxy command), causing a
chicken-and-egg problem where the extension couldn't connect because
the relay wasn't started yet.

This change starts the browser control service eagerly when Node Host
starts (if browser proxy is enabled), ensuring the relay server on
port 18792 is available for Chrome extension connections.

Security: No change to security model - relay remains loopback-only
(127.0.0.1) with existing connection validation.
Add a new `cookies` action to the browser tool that allows retrieving
browser cookies including HttpOnly cookies via Playwright CDP.

Features:
- Retrieve all cookies from the browser context
- Filter cookies by domain using the `domain` parameter
- Support both local browser control and Node Host proxy routing
- Include HttpOnly cookies (accessible via CDP, not JavaScript)

Use case: Enable MCP server authentication token refresh by extracting
session cookies from authenticated browser sessions.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Feb 3, 2026

@greptile-apps greptile-apps 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.

2 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +723 to +731
if (proxyRequest) {
const result = (await proxyRequest({
method: "GET",
path: "/cookies",
profile,
query: {
targetId,
},
})) as { ok: boolean; targetId: string; cookies: unknown[] };

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.

[P0] domain filter is ignored when calling the node proxy.

In the node-proxy path you only include targetId in query, so domain never reaches the node-host /cookies route. This means browser action="cookies" target="node" domain=... will return unfiltered cookies unless the server happens to filter some other way. (You currently filter client-side after the proxy call, but that assumes the proxy always returns all cookies, which is both inefficient and may not match intended semantics.)

Also appears in src/agents/tools/browser-tool.test.ts:367 (test name implies proxy-side filter but current implementation is client-side).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/tools/browser-tool.ts
Line: 723:731

Comment:
[P0] `domain` filter is ignored when calling the node proxy.

In the node-proxy path you only include `targetId` in `query`, so `domain` never reaches the node-host `/cookies` route. This means `browser action="cookies" target="node" domain=...` will return *unfiltered* cookies unless the server happens to filter some other way. (You currently filter client-side after the proxy call, but that assumes the proxy always returns *all* cookies, which is both inefficient and may not match intended semantics.)

Also appears in `src/agents/tools/browser-tool.test.ts:367` (test name implies proxy-side filter but current implementation is client-side).

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

Comment thread src/browser/client.ts
Comment on lines +369 to +372
const result = await fetchBrowserJson<BrowserCookiesResult>(
withBaseUrl(baseUrl, `/cookies?${q.toString()}`),
{ timeoutMs: 10000 },
);

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] /cookies URL always includes a trailing ?, which can break routing.

withBaseUrl(baseUrl, /cookies?${q.toString()}) produces /cookies? when q is empty. Some routers/middlewares treat /cookies and /cookies? differently, which can lead to 404s or cache misses. Safer to omit the ? when there are no query params.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/browser/client.ts
Line: 369:372

Comment:
[P1] `/cookies` URL always includes a trailing `?`, which can break routing.

`withBaseUrl(baseUrl, `/cookies?${q.toString()}`)` produces `/cookies?` when `q` is empty. Some routers/middlewares treat `/cookies` and `/cookies?` differently, which can lead to 404s or cache misses. Safer to omit the `?` when there are no query params.

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

Comment thread src/browser/client.ts
Comment on lines +374 to +379
if (opts?.domain) {
const domainFilter = opts.domain.toLowerCase();
result.cookies = result.cookies.filter((c) =>
c.domain.toLowerCase().includes(domainFilter),
);
}

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] Client-side domain filtering duplicates server/proxy behavior and can hide bugs.

browserCookies() fetches from /cookies then filters result.cookies client-side. If the server later adds domain filtering (or already does for some backends), the client filtering can mask issues and makes it harder to reason about what the API returns. Consider pushing domain down into the request query (so all backends filter consistently) and keeping client-side filtering only as a fallback (or removing it).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/browser/client.ts
Line: 374:379

Comment:
[P2] Client-side domain filtering duplicates server/proxy behavior and can hide bugs.

`browserCookies()` fetches from `/cookies` then filters `result.cookies` client-side. If the server later adds domain filtering (or already does for some backends), the client filtering can mask issues and makes it harder to reason about what the API returns. Consider pushing `domain` down into the request query (so all backends filter consistently) and keeping client-side filtering only as a fallback (or removing it).

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

- Fix URL query string formatting (P1): avoid trailing '?' when no params
- Add comment clarifying client-side domain filtering (P0/P2)
- Fix lint errors in test file (no-unsafe-optional-chaining)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@euisuk-chung euisuk-chung closed this by deleting the head repository Feb 21, 2026
globalcaos added a commit to globalcaos/tinkerclaw that referenced this pull request Mar 8, 2026
…mory

YouTube Ultimate v2.0.0:
- Added yt-dlp integration for video/audio downloads
- formats command to list available qualities
- 4K/1440p support, FLAC/WAV/OPUS audio
- Cookie support for age-restricted content
- Robust error handling

WhatsApp Full History Sync:
- New config option: syncFullHistory (opt-in)
- Handles messaging-history.set events from Baileys
- Enables reading all past messages (one-time sync at pairing)

LanceDB Hybrid Memory:
- Cherry-picked openclaw#7695 + openclaw#7636 for better recall
- Hybrid search combining vector + keyword

Also includes:
- openclaw#7747 Zero-latency hot-reload
- openclaw#7635 Browser cookies action
- openclaw#7600 Secrets injection proxy

Trust-first fork: Removing restrictions, enabling full AI access.
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.

1 participant