Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .github/ISSUE_TEMPLATE/2_bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
---
> [!IMPORTANT]
> 🙏 Please **go check *right now before filling this out* that you are *actually* on the [⬆️ LATEST VERSION](https://github.com/browser-use/browser-use/releases)**.
> 🚀 We ship changes every hour and we might've already fixed your issue today!
> 🚀 We ship changes every hour and we might've already fixed your issue today!
> <a href="https://github.com/browser-use/browser-use/releases"><img src="https://github.com/user-attachments/assets/4cd34ee6-bafb-4f24-87e2-27a31dc5b9a4" width="500px"/></a>
> If you are running an old version, the **first thing we will ask you to do is *upgrade to the latest version* and try again**:
> - 🆕 [`beta`](https://docs.browser-use.com/development/local-setup): `uv pip install --upgrade git+https://github.com/browser-use/browser-use.git@main`
Expand All @@ -25,7 +25,7 @@ body:
attributes:
label: Browser Use Version
description: |
What exact version of `browser-use` are you using? (Run `uv pip show browser-use` or `git log -n 1`)
What exact version of `browser-use` are you using? (Run `uv pip show browser-use` or `git log -n 1`)
**DO NOT WRITE `latest release` or `main` or a very old version or we will close your issue!**
placeholder: "e.g. 0.4.45 or 62760baaefd"
validations:
Expand Down Expand Up @@ -58,7 +58,7 @@ body:

agent = Agent(
task='...',
llm=ChatOpenAI(model="gpt-4o"),
llm=ChatOpenAI(model="gpt-4.1-mini"),
browser_session=BrowserSession(headless=False),
)
...
Expand All @@ -70,8 +70,6 @@ body:
description: Which LLM model(s) are you using?
multiple: true
options:
- gpt-4o
- gpt-4o-mini
- gpt-4
- gpt-4.1
- gpt-4.1-mini
Expand Down
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@
[![Weave Badge](https://img.shields.io/endpoint?url=https%3A%2F%2Fapp.workweave.ai%2Fapi%2Frepository%2Fbadge%2Forg_T5Pvn3UBswTHIsN1dWS3voPg%2F881458615&labelColor=#EC6341)](https://app.workweave.ai/reports/repository/org_T5Pvn3UBswTHIsN1dWS3voPg/881458615)

<!-- Keep these links. Translations will automatically update with the README. -->
[Deutsch](https://www.readme-i18n.com/browser-use/browser-use?lang=de) |
[Español](https://www.readme-i18n.com/browser-use/browser-use?lang=es) |
[français](https://www.readme-i18n.com/browser-use/browser-use?lang=fr) |
[日本語](https://www.readme-i18n.com/browser-use/browser-use?lang=ja) |
[한국어](https://www.readme-i18n.com/browser-use/browser-use?lang=ko) |
[Português](https://www.readme-i18n.com/browser-use/browser-use?lang=pt) |
[Русский](https://www.readme-i18n.com/browser-use/browser-use?lang=ru) |
[Deutsch](https://www.readme-i18n.com/browser-use/browser-use?lang=de) |
[Español](https://www.readme-i18n.com/browser-use/browser-use?lang=es) |
[français](https://www.readme-i18n.com/browser-use/browser-use?lang=fr) |
[日本語](https://www.readme-i18n.com/browser-use/browser-use?lang=ja) |
[한국어](https://www.readme-i18n.com/browser-use/browser-use?lang=ko) |
[Português](https://www.readme-i18n.com/browser-use/browser-use?lang=pt) |
[Русский](https://www.readme-i18n.com/browser-use/browser-use?lang=ru) |
[中文](https://www.readme-i18n.com/browser-use/browser-use?lang=zh)

🌤️ Want to skip the setup? Use our <b>[cloud](https://cloud.browser-use.com)</b> for faster, scalable, stealth-enabled browser automation!

**🚀 Use the latest version!**
**🚀 Use the latest version!**

> We ship every day improvements for **speed**, **accuracy**, and **UX**.
> We ship every day improvements for **speed**, **accuracy**, and **UX**.
> ```bash
> uv pip install --upgrade browser-use
> ```
Expand Down Expand Up @@ -74,6 +74,22 @@ OPENAI_API_KEY=

For other settings, models, and more, check out the [documentation 📕](https://docs.browser-use.com).

**🌤️ Want to use cloud browsers?** Simply add `cloud_browser=True` to your Browser config:

```python
from browser_use import Agent, Browser, ChatOpenAI

agent = Agent(
task="Find the number of stars of the browser-use repo",
llm=ChatOpenAI(model="gpt-4.1-mini"),
browser=Browser(cloud_browser=True), # Uses Browser-Use cloud service
)
```

First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Please adjust the sentence to clearly instruct users to set the environment variable, e.g., “First set the BROWSER_USE_API_KEY environment variable. You can get your API key from here.” This improves readability and reduces confusion.

Prompt for AI agents
Address the following comment on README.md at line 89:

<comment>Please adjust the sentence to clearly instruct users to set the environment variable, e.g., “First set the `BROWSER_USE_API_KEY` environment variable. You can get your API key from here.” This improves readability and reduces confusion.</comment>

<file context>
@@ -74,6 +74,22 @@ OPENAI_API_KEY=
+)
+```
+
+First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
+
+For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Suggested change
First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
First set the `BROWSER_USE_API_KEY` environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The new sentence has a grammatical error (Set is capitalized mid-sentence and the is missing before the environment variable), which reduces clarity. Please rewrite it for proper grammar.

Prompt for AI agents
Address the following comment on README.md at line 89:

<comment>The new sentence has a grammatical error (`Set` is capitalized mid-sentence and `the` is missing before the environment variable), which reduces clarity. Please rewrite it for proper grammar.</comment>

<file context>
@@ -74,6 +74,22 @@ OPENAI_API_KEY=
+)
+```
+
+First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
+
+For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Suggested change
First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
First set the BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The new sentence has incorrect capitalization and is missing an article, which makes the documentation harder to read. Please rewrite it for proper grammar.

Prompt for AI agents
Address the following comment on README.md at line 89:

<comment>The new sentence has incorrect capitalization and is missing an article, which makes the documentation harder to read. Please rewrite it for proper grammar.</comment>

<file context>
@@ -74,6 +74,22 @@ OPENAI_API_KEY=
+)
+```
+
+First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
+
+For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: General AI Review Agent

Suggested change
First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
First set the `BROWSER_USE_API_KEY` environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Fix with Cubic

Copy link
Copy Markdown

@cubic-staging cubic-staging Bot Dec 5, 2025

Choose a reason for hiding this comment

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

P3: Grammar issue: "Set" should be lowercase "set". Consider rephrasing to "First, set the BROWSER_USE_API_KEY environment variable."

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 89:

<comment>Grammar issue: &quot;Set&quot; should be lowercase &quot;set&quot;. Consider rephrasing to &quot;First, set the BROWSER_USE_API_KEY environment variable.&quot;</comment>

<file context>
@@ -74,6 +74,22 @@ OPENAI_API_KEY=
+)
+```
+
+First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
+
+For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: General AI Review Agent

Suggested change
First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
First, set the `BROWSER_USE_API_KEY` environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Fix with Cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Jan 10, 2026

Choose a reason for hiding this comment

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

P3: Incorrect capitalization: 'Set' should be lowercase in 'First set'

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 89:

<comment>Incorrect capitalization: 'Set' should be lowercase in 'First set'</comment>

<file context>
@@ -74,6 +74,22 @@ OPENAI_API_KEY=
+)
+```
+
+First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
+
+For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: General AI Review Agent

Fix confidence: 10/10

Suggested change
First Set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
First set BROWSER_USE_API_KEY environment variable. You can get your API key from [here](https://cloud.browser-use.com).
Fix with Cubic


For other settings, models, and more, check out the [Cloud documentation 📕](https://docs.cloud.browser-use.com).

# Demos

<br/><br/>
Expand Down Expand Up @@ -254,11 +270,11 @@ If you use Browser Use in your research or project, please cite:
}
```

<div align="center"> <img src="https://github.com/user-attachments/assets/06fa3078-8461-4560-b434-445510c1766f" width="400"/>
<div align="center"> <img src="https://github.com/user-attachments/assets/06fa3078-8461-4560-b434-445510c1766f" width="400"/>

[![Twitter Follow](https://img.shields.io/twitter/follow/Gregor?style=social)](https://x.com/intent/user?screen_name=gregpr07)
[![Twitter Follow](https://img.shields.io/twitter/follow/Magnus?style=social)](https://x.com/intent/user?screen_name=mamagnus00)

</div>

<div align="center">
Expand Down
286 changes: 286 additions & 0 deletions browser_use/browser/cloud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
"""Cloud browser service integration for browser-use.
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Jan 10, 2026

Choose a reason for hiding this comment

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

P2: [Orchestrator] Concurrent cloud browser sessions cannot be tracked independently. The global _cloud_client singleton stores only the most recent current_session_id, so when multiple BrowserSession instances use cloud browsers, earlier sessions lose their session ID reference and cannot properly stop their cloud browsers, causing resource leaks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser_use/browser/cloud.py, line 109:

<comment>[Orchestrator] Concurrent cloud browser sessions cannot be tracked independently. The global `_cloud_client` singleton stores only the most recent `current_session_id`, so when multiple `BrowserSession` instances use cloud browsers, earlier sessions lose their session ID reference and cannot properly stop their cloud browsers, causing resource leaks.</comment>

<file context>
@@ -0,0 +1,286 @@
+			browser_response = CloudBrowserResponse(**browser_data)
+
+			# Store session ID for cleanup
+			self.current_session_id = browser_response.id
+
+			logger.info(f'🌤️ Cloud browser created successfully: {browser_response.id}')
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: Orchestrator AI Review Agent

Fix with Cubic


This module provides integration with the browser-use cloud browser service.
When cloud_browser=True, it automatically creates a cloud browser instance
and returns the CDP URL for connection.
"""

import logging
import os

import httpx
from pydantic import BaseModel, Field

from browser_use.sync.auth import CloudAuthConfig

logger = logging.getLogger(__name__)


class CloudBrowserResponse(BaseModel):
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Jan 10, 2026

Choose a reason for hiding this comment

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

P2: CloudBrowserResponse lacks model_config. Consider adding model_config = ConfigDict(extra='forbid') to reject unexpected API response fields, following the pattern used in TabInfo and other project models.

    DEV MODE: This violation would have been filtered out by GPT-5.

Reasoning:
GPT-5: This is a consistency/style suggestion rather than a bug. Looking at the same views.py file, PageInfo also lacks model_config, showing the pattern is not universally applied in the project. More importantly, for an API response model like CloudBrowserResponse, using extra='forbid' could be counterproductive: if the cloud API adds new fields in future versions, the client would fail to parse responses instead of gracefully ignoring unknown fields. This is a forward compatibility consideration that makes the current approach actually appropriate for this use case.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser_use/browser/cloud.py, line 19:

<comment>CloudBrowserResponse lacks `model_config`. Consider adding `model_config = ConfigDict(extra='forbid')` to reject unexpected API response fields, following the pattern used in `TabInfo` and other project models.

        DEV MODE: This violation would have been filtered out by GPT-5.
Reasoning:
• **GPT-5**: This is a consistency/style suggestion rather than a bug. Looking at the same views.py file, PageInfo also lacks model_config, showing the pattern is not universally applied in the project. More importantly, for an API response model like CloudBrowserResponse, using `extra='forbid'` could be counterproductive: if the cloud API adds new fields in future versions, the client would fail to parse responses instead of gracefully ignoring unknown fields. This is a forward compatibility consideration that makes the current approach actually appropriate for this use case.</comment>

<file context>
@@ -0,0 +1,286 @@
+logger = logging.getLogger(__name__)
+
+
+class CloudBrowserResponse(BaseModel):
+	"""Response from cloud browser API."""
+
</file context>

[internal] Confidence score: 7/10

[internal] Posted by: General AI Review Agent

Fix with Cubic

"""Response from cloud browser API."""

id: str
status: str
liveUrl: str = Field(alias='liveUrl')
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Jan 10, 2026

Choose a reason for hiding this comment

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

P3: Redundant Field aliases where alias equals field name. Pydantic uses field names by default, so Field(alias='liveUrl') on a field named liveUrl is unnecessary. Either remove the aliases or use snake_case field names with camelCase aliases for consistency.

DEV MODE: This violation would have been filtered out by screening filters. Failing filters: functionalImpact.

    DEV MODE: This violation would have been filtered out by GPT-5.

Reasoning:
GPT-5: This is a pure style/nitpick issue with zero functional impact. While technically correct that the aliases are redundant (Pydantic uses field names by default), the code works identically with or without these aliases. This is the kind of low-impact formatting/style suggestion that should not be flagged according to the review guidelines.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser_use/browser/cloud.py, line 24:

<comment>Redundant Field aliases where alias equals field name. Pydantic uses field names by default, so `Field(alias='liveUrl')` on a field named `liveUrl` is unnecessary. Either remove the aliases or use snake_case field names with camelCase aliases for consistency.

*DEV MODE: This violation would have been filtered out by screening filters. Failing filters: functionalImpact.*

        DEV MODE: This violation would have been filtered out by GPT-5.
Reasoning:
• **GPT-5**: This is a pure style/nitpick issue with zero functional impact. While technically correct that the aliases are redundant (Pydantic uses field names by default), the code works identically with or without these aliases. This is the kind of low-impact formatting/style suggestion that should not be flagged according to the review guidelines.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+	id: str
+	status: str
+	liveUrl: str = Field(alias='liveUrl')
+	cdpUrl: str = Field(alias='cdpUrl')
+	timeoutAt: str = Field(alias='timeoutAt')
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: General AI Review Agent

Fix with Cubic

cdpUrl: str = Field(alias='cdpUrl')
timeoutAt: str = Field(alias='timeoutAt')
startedAt: str = Field(alias='startedAt')
finishedAt: str | None = Field(alias='finishedAt', default=None)


class CloudBrowserError(Exception):
"""Exception raised when cloud browser operations fail."""

pass


class CloudBrowserAuthError(CloudBrowserError):
"""Exception raised when cloud browser authentication fails."""

pass


class CloudBrowserClient:
"""Client for browser-use cloud browser service."""

def __init__(self, api_base_url: str = 'https://api.browser-use.com'):
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Hard-coding the cloud API base URL here ignores the existing BROWSER_USE_CLOUD_API_URL configuration, so anyone pointing the client at staging or mocked endpoints cannot use the new cloud browser feature. Please default to the configurable URL instead of a constant.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 46:

<comment>Hard-coding the cloud API base URL here ignores the existing `BROWSER_USE_CLOUD_API_URL` configuration, so anyone pointing the client at staging or mocked endpoints cannot use the new cloud browser feature. Please default to the configurable URL instead of a constant.</comment>

<file context>
@@ -0,0 +1,286 @@
+class CloudBrowserClient:
+	&quot;&quot;&quot;Client for browser-use cloud browser service.&quot;&quot;&quot;
+
+	def __init__(self, api_base_url: str = &#39;https://api.browser-use.com&#39;):
+		self.api_base_url = api_base_url
+		self.client = httpx.AsyncClient(timeout=30.0)
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Fix with Cubic

self.api_base_url = api_base_url
self.client = httpx.AsyncClient(timeout=30.0)
self.current_session_id: str | None = None

async def create_browser(self) -> CloudBrowserResponse:
"""Create a new cloud browser instance.

Returns:
CloudBrowserResponse: Contains CDP URL and other browser info

Raises:
CloudBrowserAuthError: If authentication fails
CloudBrowserError: If browser creation fails
"""
url = f'{self.api_base_url}/api/v2/browsers'

# Try to get API key from environment variable first, then auth config
api_token = os.getenv('BROWSER_USE_API_KEY')
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

API token retrieval logic duplicates within CloudBrowserClient. This authentication pattern should be centralized into a single helper method (e.g., _get_api_token) within the CloudBrowserClient class to ensure consistency and easier maintenance of authentication logic.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>API token retrieval logic duplicates within CloudBrowserClient. This authentication pattern should be centralized into a single helper method (e.g., `_get_api_token`) within the `CloudBrowserClient` class to ensure consistency and easier maintenance of authentication logic.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The method for managing the cloud browser API key is inconsistent with the established configuration pattern for other credentials in the project. This new feature introduces a separate configuration file (cloud_auth.json) and also checks for an environment variable, fragmenting the configuration and making it harder to manage.

DEV MODE: This violation would have been filtered out by screening filters. Failing filters: functionalImpact.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>The method for managing the cloud browser API key is inconsistent with the established configuration pattern for other credentials in the project. This new feature introduces a separate configuration file (`cloud_auth.json`) and also checks for an environment variable, fragmenting the configuration and making it harder to manage.

*DEV MODE: This violation would have been filtered out by screening filters. Failing filters: functionalImpact.*</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

API token retrieval logic is duplicated within the CloudBrowserClient class. This critical authentication pattern should be extracted into a shared helper method.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>API token retrieval logic is duplicated within the `CloudBrowserClient` class. This critical authentication pattern should be extracted into a shared helper method.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

API token retrieval logic duplicates itself within the CloudBrowserClient class in browser_use/browser/cloud.py. This critical authentication pattern should be centralized into a shared helper method.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>API token retrieval logic duplicates itself within the CloudBrowserClient class in browser_use/browser/cloud.py. This critical authentication pattern should be centralized into a shared helper method.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Authentication token retrieval logic is duplicated within CloudBrowserClient.create_browser() and CloudBrowserClient.stop_browser(). This critical logic should be centralized to ensure consistent authentication and easier maintenance.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>Authentication token retrieval logic is duplicated within `CloudBrowserClient.create_browser()` and `CloudBrowserClient.stop_browser()`. This critical logic should be centralized to ensure consistent authentication and easier maintenance.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

API token retrieval logic duplicates in CloudBrowserClient.create_browser() and CloudBrowserClient.stop_browser(). This authentication pattern already exists with CloudAuthConfig.load_from_file() in browser_use/sync/auth.py and should be centralized into a single helper function.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>API token retrieval logic duplicates in `CloudBrowserClient.create_browser()` and `CloudBrowserClient.stop_browser()`. This authentication pattern already exists with `CloudAuthConfig.load_from_file()` in `browser_use/sync/auth.py` and should be centralized into a single helper function.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Authentication token retrieval logic is duplicated within CloudBrowserClient.create_browser() and CloudBrowserClient.stop_browser(). This logic should be extracted into a shared helper method.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>Authentication token retrieval logic is duplicated within CloudBrowserClient.create_browser() and CloudBrowserClient.stop_browser(). This logic should be extracted into a shared helper method.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9.5/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 7, 2025

Choose a reason for hiding this comment

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

API token retrieval logic is duplicated in CloudBrowserClient.create_browser() and CloudBrowserClient.stop_browser(). This pattern also exists in browser_use/sync/auth.py.

    DEV MODE: This violation would have been filtered out by GPT-5.

Reasoning:
GPT-5: The two methods in CloudBrowserClient do repeat the simple API-token lookup, but this is a small, straightforward block that does not pose a significant maintenance risk. Moreover, the explanation incorrectly claims the same logic exists in browser_use/sync/auth.py, which does not perform the environment-variable fallback. Given the low impact and partially inaccurate evidence, this should not be reported.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 64:

<comment>API token retrieval logic is duplicated in `CloudBrowserClient.create_browser()` and `CloudBrowserClient.stop_browser()`. This pattern also exists in `browser_use/sync/auth.py`.

        DEV MODE: This violation would have been filtered out by GPT-5.
Reasoning:
• **GPT-5**: The two methods in CloudBrowserClient do repeat the simple API-token lookup, but this is a small, straightforward block that does not pose a significant maintenance risk. Moreover, the explanation incorrectly claims the same logic exists in browser_use/sync/auth.py, which does not perform the environment-variable fallback. Given the low impact and partially inaccurate evidence, this should not be reported.</comment>

<file context>
@@ -0,0 +1,286 @@
+		url = f&#39;{self.api_base_url}/api/v2/browsers&#39;
+
+		# Try to get API key from environment variable first, then auth config
+		api_token = os.getenv(&#39;BROWSER_USE_API_KEY&#39;)
+
+		if not api_token:
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic


if not api_token:
# Fallback to auth config file
try:
auth_config = CloudAuthConfig.load_from_file()
api_token = auth_config.api_token
except Exception:
pass

if not api_token:
raise CloudBrowserAuthError(
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

API token retrieval and validation logic is duplicated between create_browser and stop_browser in browser_use/browser/cloud.py. This impacts consistent authentication behavior and maintainability.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 75:

<comment>API token retrieval and validation logic is duplicated between `create_browser` and `stop_browser` in `browser_use/browser/cloud.py`. This impacts consistent authentication behavior and maintainability.</comment>

<file context>
@@ -0,0 +1,286 @@
+				pass
+
+		if not api_token:
+			raise CloudBrowserAuthError(
+				&#39;No authentication token found. Please set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.&#39;
+			)
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: Duplicate Detection Agent

Fix with Cubic

'No authentication token found. Please set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.'
)

headers = {'X-Browser-Use-API-Key': api_token, 'Content-Type': 'application/json'}

# Empty request body as per API specification
request_body = {}

try:
logger.info('🌤️ Creating cloud browser instance...')

response = await self.client.post(url, headers=headers, json=request_body)

if response.status_code == 401:
raise CloudBrowserAuthError(
'Authentication failed. Please make sure you have set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.'
)
elif response.status_code == 403:
raise CloudBrowserAuthError('Access forbidden. Please check your browser-use cloud subscription status.')
elif not response.is_success:
error_msg = f'Failed to create cloud browser: HTTP {response.status_code}'
try:
error_data = response.json()
if 'detail' in error_data:
error_msg += f' - {error_data["detail"]}'
except Exception:
pass
raise CloudBrowserError(error_msg)

browser_data = response.json()
browser_response = CloudBrowserResponse(**browser_data)

# Store session ID for cleanup
self.current_session_id = browser_response.id
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Storing the cloud session id on the shared client means only the newest session is tracked. If two BrowserSession instances start cloud browsers, the second call overwrites current_session_id, so the first session’s cleanup stops the wrong browser (and the other session leaks). Please return/propagate the session id so each caller cleans up its own instance instead of relying on shared state.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 109:

<comment>Storing the cloud session id on the shared client means only the newest session is tracked. If two BrowserSession instances start cloud browsers, the second call overwrites `current_session_id`, so the first session’s cleanup stops the wrong browser (and the other session leaks). Please return/propagate the session id so each caller cleans up its own instance instead of relying on shared state.</comment>

<file context>
@@ -0,0 +1,286 @@
+			browser_response = CloudBrowserResponse(**browser_data)
+
+			# Store session ID for cleanup
+			self.current_session_id = browser_response.id
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Fix with Cubic


logger.info(f'🌤️ Cloud browser created successfully: {browser_response.id}')
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Sensitive data exposure: cdpUrl logged at debug allows session hijacking via logs.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 112:

<comment>Sensitive data exposure: cdpUrl logged at debug allows session hijacking via logs.</comment>

<file context>
@@ -0,0 +1,286 @@
+			self.current_session_id = browser_response.id
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
+			logger.debug(f&#39;🌤️ CDP URL: {browser_response.cdpUrl}&#39;)
+			logger.debug(f&#39;🌤️ Live URL: {browser_response.liveUrl}&#39;)
+
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Security Vulnerabilities Agent

Suggested change
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
logger.debug('🌤️ CDP URL obtained')
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Logging the CDP URL exposes the authenticated remote debugging endpoint for the live cloud browser session; anyone with log access could hijack the browser. Please drop or redact this log line so the URL never leaves process memory.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 112:

<comment>Logging the CDP URL exposes the authenticated remote debugging endpoint for the live cloud browser session; anyone with log access could hijack the browser. Please drop or redact this log line so the URL never leaves process memory.</comment>

<file context>
@@ -0,0 +1,286 @@
+			self.current_session_id = browser_response.id
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
+			logger.debug(f&#39;🌤️ CDP URL: {browser_response.cdpUrl}&#39;)
+			logger.debug(f&#39;🌤️ Live URL: {browser_response.liveUrl}&#39;)
+
</file context>

[internal] Confidence score: 7/10

[internal] Posted by: General AI Review Agent

Suggested change
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
logger.debug('🌤️ Cloud browser created successfully (CDP URL hidden)')
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Sensitive data exposure: CDP URL is logged, enabling unauthorized remote control if logs are accessed.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 112:

<comment>Sensitive data exposure: CDP URL is logged, enabling unauthorized remote control if logs are accessed.</comment>

<file context>
@@ -0,0 +1,286 @@
+			self.current_session_id = browser_response.id
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
+			logger.debug(f&#39;🌤️ CDP URL: {browser_response.cdpUrl}&#39;)
+			logger.debug(f&#39;🌤️ Live URL: {browser_response.liveUrl}&#39;)
+
</file context>

[internal] Confidence score: 9/10

[internal] Posted by: Security Vulnerabilities Agent

Suggested change
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
logger.debug('🌤️ CDP URL obtained')
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 7, 2025

Choose a reason for hiding this comment

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

Avoid logging the CDP endpoint; it exposes the remote-debugging URL and would let anyone with log access hijack the session.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 112:

<comment>Avoid logging the CDP endpoint; it exposes the remote-debugging URL and would let anyone with log access hijack the session.</comment>

<file context>
@@ -0,0 +1,286 @@
+			self.current_session_id = browser_response.id
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
+			logger.debug(f&#39;🌤️ CDP URL: {browser_response.cdpUrl}&#39;)
+			logger.debug(f&#39;🌤️ Live URL: {browser_response.liveUrl}&#39;)
+
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Suggested change
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
logger.debug('🌤️ Cloud browser connection established')
Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Jan 10, 2026

Choose a reason for hiding this comment

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

P2: [Orchestrator] Sensitive CDP and Live URLs containing session identifiers are logged at DEBUG level. These URLs effectively act as credentials for accessing cloud browser sessions. Consider logging only a masked portion (e.g., session ID prefix) or removing these debug statements to prevent potential session hijacking via log exposure.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At browser_use/browser/cloud.py, line 112:

<comment>[Orchestrator] Sensitive CDP and Live URLs containing session identifiers are logged at DEBUG level. These URLs effectively act as credentials for accessing cloud browser sessions. Consider logging only a masked portion (e.g., session ID prefix) or removing these debug statements to prevent potential session hijacking via log exposure.</comment>

<file context>
@@ -0,0 +1,286 @@
+			self.current_session_id = browser_response.id
+
+			logger.info(f'🌤️ Cloud browser created successfully: {browser_response.id}')
+			logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
+			logger.debug(f'🌤️ Live URL: {browser_response.liveUrl}')
+
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: Orchestrator AI Review Agent

Fix with Cubic

logger.debug(f'🌤️ Live URL: {browser_response.liveUrl}')
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 7, 2025

Choose a reason for hiding this comment

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

Avoid logging the live-view URL; publishing it to logs shares a sensitive link that grants access to the running cloud browser session.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 113:

<comment>Avoid logging the live-view URL; publishing it to logs shares a sensitive link that grants access to the running cloud browser session.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+			logger.info(f&#39;🌤️ Cloud browser created successfully: {browser_response.id}&#39;)
+			logger.debug(f&#39;🌤️ CDP URL: {browser_response.cdpUrl}&#39;)
+			logger.debug(f&#39;🌤️ Live URL: {browser_response.liveUrl}&#39;)
+
+			return browser_response
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: General AI Review Agent

Suggested change
logger.debug(f'🌤️ Live URL: {browser_response.liveUrl}')
logger.debug('🌤️ Cloud browser live view ready')
Fix with Cubic


return browser_response

except httpx.TimeoutException:
raise CloudBrowserError('Timeout while creating cloud browser. Please try again.')
except httpx.ConnectError:
raise CloudBrowserError('Failed to connect to cloud browser service. Please check your internet connection.')
except Exception as e:
if isinstance(e, (CloudBrowserError, CloudBrowserAuthError)):
raise
raise CloudBrowserError(f'Unexpected error creating cloud browser: {e}')

async def stop_browser(self, session_id: str | None = None) -> CloudBrowserResponse:
"""Stop a cloud browser session.

Args:
session_id: Session ID to stop. If None, uses current session.

Returns:
CloudBrowserResponse: Updated browser info with stopped status

Raises:
CloudBrowserAuthError: If authentication fails
CloudBrowserError: If stopping fails
"""
if session_id is None:
session_id = self.current_session_id

if not session_id:
raise CloudBrowserError('No session ID provided and no current session available')

url = f'{self.api_base_url}/api/v2/browsers/{session_id}'

# Try to get API key from environment variable first, then auth config
api_token = os.getenv('BROWSER_USE_API_KEY')

if not api_token:
# Fallback to auth config file
try:
auth_config = CloudAuthConfig.load_from_file()
api_token = auth_config.api_token
except Exception:
pass

if not api_token:
raise CloudBrowserAuthError(
'No authentication token found. Please set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.'
)

headers = {'X-Browser-Use-API-Key': api_token, 'Content-Type': 'application/json'}

request_body = {'action': 'stop'}

try:
logger.info(f'🌤️ Stopping cloud browser session: {session_id}')

response = await self.client.patch(url, headers=headers, json=request_body)

if response.status_code == 401:
raise CloudBrowserAuthError(
'Authentication failed. Please make sure you have set the BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.'
)
elif response.status_code == 404:
# Session already stopped or doesn't exist - treating as error and clearing session
logger.debug(f'🌤️ Cloud browser session {session_id} not found (already stopped)')
# Clear current session if it was this one
if session_id == self.current_session_id:
self.current_session_id = None
raise CloudBrowserError(f'Cloud browser session {session_id} not found')
elif not response.is_success:
error_msg = f'Failed to stop cloud browser: HTTP {response.status_code}'
try:
error_data = response.json()
if 'detail' in error_data:
error_msg += f' - {error_data["detail"]}'
except Exception:
pass
raise CloudBrowserError(error_msg)

browser_data = response.json()
browser_response = CloudBrowserResponse(**browser_data)

# Clear current session if it was this one
if session_id == self.current_session_id:
self.current_session_id = None

logger.info(f'🌤️ Cloud browser session stopped: {browser_response.id}')
logger.debug(f'🌤️ Status: {browser_response.status}')

return browser_response

except httpx.TimeoutException:
raise CloudBrowserError('Timeout while stopping cloud browser. Please try again.')
except httpx.ConnectError:
raise CloudBrowserError('Failed to connect to cloud browser service. Please check your internet connection.')
except Exception as e:
if isinstance(e, (CloudBrowserError, CloudBrowserAuthError)):
raise
raise CloudBrowserError(f'Unexpected error stopping cloud browser: {e}')

async def close(self):
"""Close the HTTP client and cleanup any active sessions."""
# Try to stop current session if active
if self.current_session_id:
try:
await self.stop_browser()
except Exception as e:
logger.debug(f'Failed to stop cloud browser session during cleanup: {e}')

await self.client.aclose()


# Global client instance
_cloud_client: CloudBrowserClient | None = None
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a global _cloud_client with a mutable current_session_id is not safe for concurrency. If multiple cloud sessions are initiated in parallel, session IDs will be overwritten, causing all but the last session to be orphaned in the cloud without proper cleanup.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The use of a global `_cloud_client` with a mutable `current_session_id` is not safe for concurrency. If multiple cloud sessions are initiated in parallel, session IDs will be overwritten, causing all but the last session to be orphaned in the cloud without proper cleanup.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a global singleton for CloudBrowserClient introduces a race condition when multiple cloud-based BrowserSession instances are used concurrently, leading to incorrect session cleanup and potential resource leaks. The client's lifecycle should be tied to the BrowserSession instance itself, not managed globally.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The use of a global singleton for `CloudBrowserClient` introduces a race condition when multiple cloud-based `BrowserSession` instances are used concurrently, leading to incorrect session cleanup and potential resource leaks. The client&#39;s lifecycle should be tied to the `BrowserSession` instance itself, not managed globally.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a global stateful client for managing cloud browsers is not thread-safe and will cause race conditions. If multiple cloud BrowserSessions are active concurrently, stopping one will terminate another's browser instance, and will also cause resource leaks.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The use of a global stateful client for managing cloud browsers is not thread-safe and will cause race conditions. If multiple cloud `BrowserSession`s are active concurrently, stopping one will terminate another&#39;s browser instance, and will also cause resource leaks.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a global _cloud_client instance to manage stateful cloud browser sessions is a significant architectural flaw. This will cause race conditions and incorrect behavior when multiple cloud browser sessions are used concurrently, as they will all share and overwrite the same client state (current_session_id). The client's lifecycle should be tied to the BrowserSession.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The use of a global `_cloud_client` instance to manage stateful cloud browser sessions is a significant architectural flaw. This will cause race conditions and incorrect behavior when multiple cloud browser sessions are used concurrently, as they will all share and overwrite the same client state (`current_session_id`). The client&#39;s lifecycle should be tied to the `BrowserSession`.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a global singleton (_cloud_client) for managing cloud browser sessions is a critical architectural flaw. This design prevents running multiple concurrent cloud sessions, as creating a new session overwrites the state of the previous one, leading to incorrect session termination and orphaned cloud resources.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The use of a global singleton (`_cloud_client`) for managing cloud browser sessions is a critical architectural flaw. This design prevents running multiple concurrent cloud sessions, as creating a new session overwrites the state of the previous one, leading to incorrect session termination and orphaned cloud resources.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 7, 2025

Choose a reason for hiding this comment

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

The introduction of a global _cloud_client singleton to manage cloud browser sessions introduces a critical architectural flaw. The client instance stores current_session_id, which is state specific to a single browser session. If multiple BrowserSession instances with use_cloud=True are created concurrently, they will all share and overwrite this single global client and its current_session_id. This leads to race conditions where stopping one session can terminate the browser of another session, causing unpredictable behavior and orphaned cloud resources. The CloudBrowserClient should be instantiated per BrowserSession to ensure state isolation.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 227:

<comment>The introduction of a global `_cloud_client` singleton to manage cloud browser sessions introduces a critical architectural flaw. The client instance stores `current_session_id`, which is state specific to a single browser session. If multiple `BrowserSession` instances with `use_cloud=True` are created concurrently, they will all share and overwrite this single global client and its `current_session_id`. This leads to race conditions where stopping one session can terminate the browser of another session, causing unpredictable behavior and orphaned cloud resources. The `CloudBrowserClient` should be instantiated per `BrowserSession` to ensure state isolation.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+
+# Global client instance
+_cloud_client: CloudBrowserClient | None = None
+
+
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic



async def get_cloud_browser_cdp_url() -> str:
"""Get a CDP URL for a new cloud browser instance.

Returns:
str: CDP URL for connecting to the cloud browser

Raises:
CloudBrowserAuthError: If authentication fails
CloudBrowserError: If browser creation fails
"""
global _cloud_client

if _cloud_client is None:
_cloud_client = CloudBrowserClient()

try:
browser_response = await _cloud_client.create_browser()
return browser_response.cdpUrl
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

Returning only the CDP URL drops the session id, so creating multiple cloud sessions before stopping leaks earlier sessions because they can no longer be stopped.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 247:

<comment>Returning only the CDP URL drops the session id, so creating multiple cloud sessions before stopping leaks earlier sessions because they can no longer be stopped.</comment>

<file context>
@@ -0,0 +1,286 @@
+
+	try:
+		browser_response = await _cloud_client.create_browser()
+		return browser_response.cdpUrl
+	except Exception:
+		# Clean up client on error
</file context>

[internal] Confidence score: 8/10

[internal] Posted by: Functional Bugs Agent

Fix with Cubic

except Exception:
# Clean up client on error
if _cloud_client:
await _cloud_client.close()
_cloud_client = None
raise


async def stop_cloud_browser_session(session_id: str | None = None) -> CloudBrowserResponse:
"""Stop a cloud browser session.

Args:
session_id: Session ID to stop. If None, uses current session from global client.

Returns:
CloudBrowserResponse: Updated browser info with stopped status

Raises:
CloudBrowserAuthError: If authentication fails
CloudBrowserError: If stopping fails
"""
global _cloud_client

if _cloud_client is None:
_cloud_client = CloudBrowserClient()

try:
return await _cloud_client.stop_browser(session_id)
except Exception:
# Don't clean up client on stop errors - session might still be valid
raise


async def cleanup_cloud_client():
Copy link
Copy Markdown
Author

@cubic-dev-local cubic-dev-local Bot Nov 6, 2025

Choose a reason for hiding this comment

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

The use of a stateful global client for managing cloud browser sessions will cause incorrect session termination when multiple cloud browsers are used concurrently. The session lifecycle management should be handled within each BrowserSession instance, not through a global singleton.

Prompt for AI agents
Address the following comment on browser_use/browser/cloud.py at line 281:

<comment>The use of a stateful global client for managing cloud browser sessions will cause incorrect session termination when multiple cloud browsers are used concurrently. The session lifecycle management should be handled within each `BrowserSession` instance, not through a global singleton.</comment>

<file context>
@@ -0,0 +1,286 @@
+		raise
+
+
+async def cleanup_cloud_client():
+	&quot;&quot;&quot;Clean up the global cloud client.&quot;&quot;&quot;
+	global _cloud_client
</file context>

[internal] Confidence score: 10/10

[internal] Posted by: System Design Agent

Fix with Cubic

"""Clean up the global cloud client."""
global _cloud_client
if _cloud_client:
await _cloud_client.close()
_cloud_client = None
Loading
Loading