Implement Docker support, WebUI API, and stealth extension#719
Implement Docker support, WebUI API, and stealth extension#719aleks1k wants to merge 1 commit intobrowser-use:mainfrom
Conversation
…les, no secrets) Made-with: Cursor
|
|
There was a problem hiding this comment.
9 issues found across 16 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/startup_browser.py">
<violation number="1" location="scripts/startup_browser.py:33">
P2: startup_browser.py only strips the "--user-data-dir=..." form. If PLAYWRIGHT_LAUNCH_ARGS contains the two-token form ("--user-data-dir /path"), user_data_dir remains None and the script falls back to a default profile while still passing the raw --user-data-dir arguments into Chromium, ignoring the intended profile. Handle the two-token form as well to avoid silently using the wrong profile.</violation>
</file>
<file name="docs/CLI_AND_DOCKER_CDP.md">
<violation number="1" location="docs/CLI_AND_DOCKER_CDP.md:79">
P2: Documentation suggests pointing CDP to a server IP without warning that the remote debugging port is unauthenticated and should be restricted; this can lead to exposing full browser control if 9222 is reachable publicly.</violation>
</file>
<file name="stealth-extension/stealth.js">
<violation number="1" location="stealth-extension/stealth.js:1">
P2: The stealth overrides are wrapped in a bare arrow function that is never invoked, so none of the property overrides execute.</violation>
<violation number="2" location="stealth-extension/stealth.js:14">
P2: `navigator.permissions` getter returns a new object each access, so the later override of `query` does not persist and the notifications-specific behavior is never applied.</violation>
<violation number="3" location="stealth-extension/stealth.js:43">
P2: Syntax error: window.chrome object literal is not closed, so the script cannot parse.</violation>
<violation number="4" location="stealth-extension/stealth.js:49">
P2: Using HTMLNavigator.prototype will throw ReferenceError in standard browsers; the Navigator interface is the correct prototype for userAgent overrides.</violation>
</file>
<file name="stealth-extension/manifest.json">
<violation number="1" location="stealth-extension/manifest.json:14">
P2: manifest.json is missing the closing `}` for the top-level object, making the JSON invalid and causing the extension to fail to load.</violation>
</file>
<file name="src/webui/browser_api.py">
<violation number="1" location="src/webui/browser_api.py:137">
P2: api_screenshot promises a base64 image but can return a filesystem path when "path" is present, breaking the API contract and potentially leaking local paths to consumers expecting base64 data.</violation>
</file>
<file name="docker-compose.yml">
<violation number="1" location="docker-compose.yml:68">
P2: noVNC is exposed on 0.0.0.0 while the default VNC_PASSWORD is empty, which results in a blank VNC password being generated and allows unauthenticated access to the VNC/noVNC UI from any host.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| user_data_dir = None | ||
| if config.extra_browser_args: | ||
| for a in config.extra_browser_args: | ||
| if a.startswith("--user-data-dir="): |
There was a problem hiding this comment.
P2: startup_browser.py only strips the "--user-data-dir=..." form. If PLAYWRIGHT_LAUNCH_ARGS contains the two-token form ("--user-data-dir /path"), user_data_dir remains None and the script falls back to a default profile while still passing the raw --user-data-dir arguments into Chromium, ignoring the intended profile. Handle the two-token form as well to avoid silently using the wrong profile.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/startup_browser.py, line 33:
<comment>startup_browser.py only strips the "--user-data-dir=..." form. If PLAYWRIGHT_LAUNCH_ARGS contains the two-token form ("--user-data-dir /path"), user_data_dir remains None and the script falls back to a default profile while still passing the raw --user-data-dir arguments into Chromium, ignoring the intended profile. Handle the two-token form as well to avoid silently using the wrong profile.</comment>
<file context>
@@ -0,0 +1,66 @@
+ user_data_dir = None
+ if config.extra_browser_args:
+ for a in config.extra_browser_args:
+ if a.startswith("--user-data-dir="):
+ user_data_dir = a.split("=", 1)[1].strip()
+ else:
</file context>
| If the host is not the same machine as the server (e.g. you’re on a laptop and the container runs on a server), replace `127.0.0.1` with the server’s IP or hostname: | ||
|
|
||
| ```python | ||
| CDP_URL = "http://YOUR_SERVER_IP:9222" |
There was a problem hiding this comment.
P2: Documentation suggests pointing CDP to a server IP without warning that the remote debugging port is unauthenticated and should be restricted; this can lead to exposing full browser control if 9222 is reachable publicly.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/CLI_AND_DOCKER_CDP.md, line 79:
<comment>Documentation suggests pointing CDP to a server IP without warning that the remote debugging port is unauthenticated and should be restricted; this can lead to exposing full browser control if 9222 is reachable publicly.</comment>
<file context>
@@ -0,0 +1,133 @@
+If the host is not the same machine as the server (e.g. you’re on a laptop and the container runs on a server), replace `127.0.0.1` with the server’s IP or hostname:
+
+```python
+CDP_URL = "http://YOUR_SERVER_IP:9222"
+```
+
</file context>
| get: () => [1, 2, 3, 4, 5], | ||
| }); | ||
|
|
||
| Object.defineProperty(navigator, 'permissions', { |
There was a problem hiding this comment.
P2: navigator.permissions getter returns a new object each access, so the later override of query does not persist and the notifications-specific behavior is never applied.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At stealth-extension/stealth.js, line 14:
<comment>`navigator.permissions` getter returns a new object each access, so the later override of `query` does not persist and the notifications-specific behavior is never applied.</comment>
<file context>
@@ -0,0 +1,51 @@
+ get: () => [1, 2, 3, 4, 5],
+ });
+
+ Object.defineProperty(navigator, 'permissions', {
+ get: () => ({
+ query: () => Promise.resolve({ state: 'granted' }),
</file context>
| get: () => window.chrome, | ||
| }); | ||
|
|
||
| Object.defineProperty(HTMLNavigator.prototype, 'userAgent', { |
There was a problem hiding this comment.
P2: Using HTMLNavigator.prototype will throw ReferenceError in standard browsers; the Navigator interface is the correct prototype for userAgent overrides.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At stealth-extension/stealth.js, line 49:
<comment>Using HTMLNavigator.prototype will throw ReferenceError in standard browsers; the Navigator interface is the correct prototype for userAgent overrides.</comment>
<file context>
@@ -0,0 +1,51 @@
+ get: () => window.chrome,
+ });
+
+ Object.defineProperty(HTMLNavigator.prototype, 'userAgent', {
+ get: () => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
+ });
</file context>
| @@ -0,0 +1,51 @@ | |||
| () => { | |||
There was a problem hiding this comment.
P2: The stealth overrides are wrapped in a bare arrow function that is never invoked, so none of the property overrides execute.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At stealth-extension/stealth.js, line 1:
<comment>The stealth overrides are wrapped in a bare arrow function that is never invoked, so none of the property overrides execute.</comment>
<file context>
@@ -0,0 +1,51 @@
+() => {
+ Object.defineProperty(navigator, 'webdriver', {
+ get: () => false,
</file context>
| canary: false, | ||
| loadTimes: () => {}, | ||
| csi: () => {}, | ||
| ; |
There was a problem hiding this comment.
P2: Syntax error: window.chrome object literal is not closed, so the script cannot parse.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At stealth-extension/stealth.js, line 43:
<comment>Syntax error: window.chrome object literal is not closed, so the script cannot parse.</comment>
<file context>
@@ -0,0 +1,51 @@
+ canary: false,
+ loadTimes: () => {},
+ csi: () => {},
+ ;
+
+ Object.defineProperty(navigator, 'chrome', {
</file context>
| "permissions": [ | ||
| "webNavigation", | ||
| "tabs" | ||
| ] |
There was a problem hiding this comment.
P2: manifest.json is missing the closing } for the top-level object, making the JSON invalid and causing the extension to fail to load.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At stealth-extension/manifest.json, line 14:
<comment>manifest.json is missing the closing `}` for the top-level object, making the JSON invalid and causing the extension to fail to load.</comment>
<file context>
@@ -0,0 +1,14 @@
+ "permissions": [
+ "webNavigation",
+ "tabs"
+ ]
</file context>
| if isinstance(out, dict) and "base64" in out: | ||
| return out["base64"] | ||
| if hasattr(out, "get"): | ||
| return out.get("base64") or out.get("path") |
There was a problem hiding this comment.
P2: api_screenshot promises a base64 image but can return a filesystem path when "path" is present, breaking the API contract and potentially leaking local paths to consumers expecting base64 data.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/webui/browser_api.py, line 137:
<comment>api_screenshot promises a base64 image but can return a filesystem path when "path" is present, breaking the API contract and potentially leaking local paths to consumers expecting base64 data.</comment>
<file context>
@@ -0,0 +1,165 @@
+ if isinstance(out, dict) and "base64" in out:
+ return out["base64"]
+ if hasattr(out, "get"):
+ return out.get("base64") or out.get("path")
+ return None
+ except Exception as e:
</file context>
|
|
||
| # VNC Settings | ||
| - VNC_PASSWORD=${VNC_PASSWORD:-youvncpassword} | ||
| - VNC_PASSWORD=${VNC_PASSWORD:-} |
There was a problem hiding this comment.
P2: noVNC is exposed on 0.0.0.0 while the default VNC_PASSWORD is empty, which results in a blank VNC password being generated and allows unauthenticated access to the VNC/noVNC UI from any host.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docker-compose.yml, line 68:
<comment>noVNC is exposed on 0.0.0.0 while the default VNC_PASSWORD is empty, which results in a blank VNC password being generated and allows unauthenticated access to the VNC/noVNC UI from any host.</comment>
<file context>
@@ -43,30 +44,35 @@ services:
# VNC Settings
- - VNC_PASSWORD=${VNC_PASSWORD:-youvncpassword}
+ - VNC_PASSWORD=${VNC_PASSWORD:-}
volumes:
</file context>
OpenClaw custom: Docker, WebUI API, stealth extension, docs" -b "Custom build for OpenClaw: Docker/docker-compose tweaks, WebUI HTTP API (browser_api), startup scripts, stealth extension, docs (WEBUI_HTTP_API.md, CLI_AND_DOCKER_CDP.md). No browser profiles or secrets in repo.
Summary by cubic
Adds Dockerized startup browser with CDP forwarding, a small WebUI HTTP API for direct browser control, and a stealth extension to make automation more stable and easier to integrate. Also adds docs and safer compose defaults so Python/CLI can connect on :9222 without exposing sensitive ports.
New Features
Migration
Written for commit b074df1. Summary will update on new commits.