Back to skill

Security audit

Win11 Visible Browser

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent, but it needs review because it can expose control of a visible logged-in browser through a powerful CDP relay and one helper prints full page URLs.

Install only if you specifically need OpenClaw to control a visible Windows browser from WSL. Prefer a dedicated browser profile, review the PowerShell script before use, require confirmation before firewall/portproxy/profile changes, verify the relay is not reachable from LAN or Internet, and avoid running the budget helper on sensitive tabs unless full URLs are redacted or acceptable to disclose.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/start-win11-browser-cdp-for-openclaw.ps1:117
Finding
Unauthenticated CDP Relay Binds to All Windows Network Interfaces<![CDATA[ ## Vulnerability Details **File Location**: `scripts/start-win11-browser-cdp-for-openclaw.ps1:59-65, 117-145` **Vulnerability Type**: `T05: Unauthorized Access and Privilege Escalation` **Risk Level**: High ### Vulnerable Code ```powershell function Get-WslCidr { $addr = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction Stop | Where-Object { ($_.InterfaceAlias -like '*WSL*' -or $_.InterfaceAlias -like '*vEthernet*') -and (Test-PrivateIPv4 $_.IPAddress) } | Sort-Object -Property InterfaceAlias | Select-Object -First 1 if (-not $addr) { throw 'Could not find WSL/Hyper-V IPv4 interface address.' } $prefix = [int]$addr.PrefixLength $ipNum = Get-IPv4UInt32 $addr.IPAddress $mask = if ($prefix -eq 0) { [uint32]0 } else { [uint32]([uint32]::MaxValue -shl (32 - $prefix)) } $network = $ipNum -band $mask $networkIp = ConvertTo-IPv4String $network return [pscustomobject]@{ InterfaceAlias = $addr.InterfaceAlias IPAddress = $addr.IPAddress PrefixLength = $prefix Cidr = "$networkIp/$prefix" } } function Ensure-PortProxy { Write-Log "Ensuring portproxy 0.0.0.0:$RelayPort -> 127.0.0.1:$CdpPort" netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=$RelayPort 2>$null | Out-Null netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=$RelayPort connectaddress=127.0.0.1 connectport=$CdpPort | Out-Null if (!(Test-HttpOk "http://127.0.0.1:$RelayPort/json/version")) { throw "Local portproxy test failed on 127.0.0.1:$RelayPort" } Write-Log "Portproxy responding locally on 127.0.0.1:$RelayPort" } function Ensure-Firewall([string]$RemoteCidr) { if (-not $RemoteCidr -or $RemoteCidr -eq '0.0.0.0/0') { throw 'Refusing to create broad firewall rule for browser CDP relay.' } Write-Log "Ensuring firewall rule '$FirewallRuleName' for remote $RemoteCidr -> TCP $RelayPort" Get-NetFirewallRule -DisplayName $OldFirewallRuleName -ErrorAction SilentlyContinue | ...[truncated 3183 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind the portproxy to the exact WSL-facing Windows IPv4 address rather than `0.0.0.0`. 2. Identify the intended WSL adapter explicitly instead of accepting every alias containing `vEthernet` and selecting the first match. 3. Verify that the selected adapter is associated with the active WSL environment and expected gateway route. 4. Reject unexpectedly broad network prefixes and require the derived CIDR to fall within an explicitly approved range. 5. Scope the firewall rule to the exact WSL source address when feasible, rather than the entire virtual subnet. 6. Restrict the firewall rule to the specific local address and appropriate network profile in addition to the remote CIDR. 7. After setup, verify the effective listening addresses with `Get-NetTCPConnection` or `netstat` and inspect the effective firewall address filters. 8. Abort and roll back the portproxy if firewall creation or post-creation validation fails. 9. Continue using a dedicated browser profile by default and require explicit approval before exposing a personal or authenticated profile. 10. Consider an authenticated local proxy or another authenticated transport if CDP must cross a network boundary. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/browser-budget-check.sh:70
Finding
Browser Budget Helper Prints Sensitive Page Titles and Complete URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/browser-budget-check.sh:70-73` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: Medium ### Vulnerable Code ```javascript console.log('Pages:'); for (const t of targets.filter(t=>t.type==='page')) { console.log(`- ${(t.title || '(untitled)').replace(/\s+/g,' ').slice(0,80)} — ${t.url}`); } ``` ### Technical Analysis The helper queries CDP's `/json/list` endpoint and prints every page target's title and complete URL to standard output. Browser URLs can contain sensitive query parameters and fragments, including search terms, internal document identifiers, invitation tokens, password-reset tokens, OAuth authorization codes, and other bearer values. Although page titles are truncated, URLs are not sanitized or truncated. Standard output may be retained in Agent transcripts, terminal logs, support records, CI output, or other diagnostic artifacts. The declared resource-budget function only requires target counts, target types, domain aggregation, and pressure indicators; complete URLs are not necessary for that purpose. This finding explains the static pre-scan's sensitive network-data pattern: the helper reads browser-session metadata from a local network CDP endpoint. No evidence shows that the project sends this information to an external collection server, but emitting it unredacted creates a secondary disclosure channel. ### Attack Path 1. A user opens a page whose URL contains private information or a bearer token. 2. The browser exposes that target through the local CDP `/json/list` endpoint. 3. The user or Agent runs `scripts/browser-budget-check.sh`. 4. The helper prints the complete sensitive URL and page title to standard output. 5. The output is stored in an Agent conversation, shell capture, diagnostic log, CI record, or support report. 6. A party with access to that retained output learns the browsing information or reuses a still-valid URL token. ### ...[truncated 573 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove full page URLs from the default budget report. 2. Report only target counts and normalized hostnames by default, which is sufficient for resource assessment. 3. If paths are required, strip query strings, fragments, embedded credentials, and other sensitive components before printing. 4. Make detailed target inventory an explicit opt-in mode and display a warning that it may reveal private browsing information. 5. Redact parameter names commonly associated with secrets, including `token`, `code`, `key`, `secret`, `auth`, `session`, and `signature`. 6. Consider hashing or pseudonymizing paths when only target deduplication is needed. 7. Avoid including detailed browser-target output in persistent Agent transcripts or diagnostic bundles unless the user explicitly approves it. 8. Add tests covering password-reset URLs, OAuth callback URLs, signed URLs, fragments, and URLs containing embedded credentials. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill explicitly instructs use of shell commands and references scripts that can modify firewall rules, portproxy settings, browser processes, Scheduled Tasks, and configuration, but it does not declare any tool scope or allowed-tools boundary. That omission weakens least-privilege controls and increases the chance an agent can invoke broader shell capabilities than intended, especially in a skill that bridges into a real user browser session with existing cookies and logins.

Context-Inappropriate Capability

Low
Confidence
82% confidence
Finding
The skill's stated purpose includes safe, human-in-the-loop visible browser control with strong tab-hygiene constraints, and earlier sections explicitly say to default to one or two tabs and 'do not open a fan-out of many result cards/resumes/products.' Line L241 promotes 'multi-tab orchestration' by opening several search results at once, which is not clearly justified given the skill's own resource-minimizing and minimal-tab workflow guidance.

Intent-Code Divergence

Low
Confidence
88% confidence
Finding
Earlier documentation says 'Default to one list/search tab and, if needed, one reusable detail tab' and 'Do not open a fan-out of many result cards/resumes/products' (L120-L123). L241 directly recommends opening several search results at once for comparison, which is an active contradiction in the skill's own documented intent and operating model.

Static analysis

No suspicious patterns detected.