Back to skill

Security audit

AI浏览器WebSocket控制

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real browser remote-control server, but it exposes too much unauthenticated control and page data without clear guardrails.

Install only in an isolated environment, bound to localhost or otherwise access-controlled, and avoid using it with sensitive logged-in accounts. Treat screenshots, DOM snapshots, typed text, and evaluate scripts as potentially exposing private data or performing real website actions.

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 (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
server.js:86
Finding
Unauthenticated WebSocket API Permits Complete Browser Control and Arbitrary Page-Context JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `server.js:75-78`, `server.js:86-113` **Vulnerability Type**: Missing authentication and authorization for a privileged browser-control interface **Risk Level**: High ### Vulnerable Code ```js case 'evaluate': if (!wsPage) throw new Error('没有活动的页面'); const result = await wsPage.evaluate(params.script); return { result }; ``` ```js // 启动 WebSocket 服务器 const wss = new WebSocket.Server({ port: PORT }); console.log(`🦞 AI Browser Server 启动在 ws://localhost:${PORT}`); wss.on('connection', (ws) => { console.log('🔌 新的客户端连接'); ws.on('message', async (message) => { try { const { action, params, id } = JSON.parse(message); console.log(`⚡ 收到指令:${action}`, params); if (!browser) await initBrowser(); if (!page) page = await browser.newPage(); if (params.targetId) { // 简单处理:如果有 targetId 且不是当前页,尝试切换(简化版暂不实现多 Tab 切换逻辑,默认单页) // 实际使用中,可以扩展为多 page 管理 } const result = await handleAction(action, params || {}); ws.send(JSON.stringify({ id, success: true, result })); } catch (error) { console.error('❌ 执行错误:', error); ws.send(JSON.stringify({ id: JSON.parse(message).id, success: false, error: error.message })); } }); ws.on('close', () => { console.log('🔌 客户端断开连接'); }); }); ``` ### Technical Analysis The WebSocket server accepts connections without authenticating the client, checking authorization, or validating the WebSocket `Origin` header. Constructing `WebSocket.Server` with only a port does not explicitly restrict the listener to the loopback interface, despite the documentation presenting the service as a localhost endpoint. Every connected client receives access to the same shared Chromium instance and page. Available actions include navigation, screenshots, DOM extraction, clicking, typing, and `ev ...[truncated 1883 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly bind the service to a loopback address unless remote access is essential: ```js const wss = new WebSocket.Server({ host: '127.0.0.1', port: PORT }); ``` 2. Require a cryptographically random, per-installation or per-session authentication token during the HTTP upgrade or initial protocol handshake. 3. Reject connections with an unapproved `Origin` header to mitigate browser-based cross-site WebSocket attacks. 4. Use TLS and client authentication if the interface must be remotely accessible. 5. Remove the unrestricted `evaluate` action. If evaluation is required, replace it with narrowly scoped, predefined operations rather than accepting JavaScript source. 6. Apply authorization independently to sensitive operations such as screenshots, DOM extraction, typing, navigation, and evaluation. 7. Allocate an isolated browser context and page per authenticated client rather than sharing one global page. 8. Add connection limits, message-size limits, request timeouts, and rate limiting. 9. Run the service under a dedicated, low-privilege operating-system account. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
server.js:47
Finding
Unrestricted Navigation Enables Browser-Based Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `server.js:47-50` **Vulnerability Type**: Browser-based server-side request forgery through an unrestricted URL **Risk Level**: High ### Vulnerable Code ```js case 'navigate': if (!wsPage) throw new Error('没有活动的页面'); await wsPage.goto(params.url, { waitUntil: 'networkidle2' }); return { success: true, url: wsPage.url(), title: await wsPage.title() }; ``` ### Technical Analysis The `navigate` action passes the client-supplied `params.url` directly to `page.goto` without validating its protocol, hostname, resolved IP address, destination port, or redirects. Consequently, a WebSocket client can use Chromium as a network proxy to request resources reachable from the service host. This may include loopback services, private network applications, link-local endpoints, or other resources that are inaccessible from the attacker's own network position. The response can subsequently be inspected through `snapshot`, `screenshot`, or `evaluate`. Browser same-origin policy does not prevent the top-level page from navigating to an internal destination, and code executed through Puppeteer can inspect the resulting document. ### Attack Path 1. The attacker connects to the unauthenticated WebSocket service. 2. The attacker submits a `navigate` action targeting an internal address, such as a loopback or private-network HTTP service. 3. Chromium issues the request from the host running this project. 4. The attacker submits an `evaluate` action that returns `document.body.innerText`, or obtains the response through a screenshot or DOM snapshot. 5. The WebSocket server serializes the extracted content and sends it to the attacker. 6. The attacker repeats the operation to enumerate internal hosts, ports, and applications or interact with internal web interfaces. ### Impact Assessment Successful exploitation may expose services and information available only from the host or its internal network. Depending on ...[truncated 492 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit only required protocols, normally `https:` and optionally `http:`. 2. Maintain a strict allowlist of approved destination hostnames rather than relying only on a denylist. 3. Resolve the destination hostname and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 4. Revalidate every redirect destination before Chromium follows it. 5. Protect against DNS rebinding by validating resolved addresses at request time and controlling outbound traffic at the network layer. 6. Block direct access to sensitive ports and non-web schemes such as `file:`, `data:`, and other unnecessary protocols. 7. Run Chromium in a network-isolated container with egress limited to explicitly approved destinations. 8. Add navigation timeouts and response-size controls to reduce denial-of-service exposure. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
server.js:18
Finding
Chromium Process Is Launched Without Its Security Sandbox<![CDATA[ ## Vulnerability Details **File Location**: `server.js:18-28` **Vulnerability Type**: Disabled browser process isolation **Risk Level**: Medium ### Vulnerable Code ```js browser = await puppeteer.launch({ headless: false, // 显示界面,方便人工介入 args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--remote-debugging-port=9222' ] }); ``` ### Technical Analysis The browser is launched with both `--no-sandbox` and `--disable-setuid-sandbox`. These switches disable important Chromium containment mechanisms intended to restrict a compromised renderer process. This is especially dangerous because the service allows clients to navigate Chromium to attacker-selected websites. A malicious site could target a browser vulnerability, and disabled sandboxing would reduce the isolation barriers between compromised browser content and the host operating system. Exploitation requires an applicable Chromium vulnerability or another browser compromise; the flags alone do not provide direct host code execution. They materially increase the consequences of such a compromise. ### Attack Path 1. An attacker obtains access to the browser-control API. 2. The attacker directs Chromium to a malicious web page. 3. The page exploits a vulnerability in the installed Chromium version or one of its browser components. 4. The compromised renderer operates without Chromium's normal sandbox containment. 5. The attacker may gain access to resources available to the operating-system account running the Node.js service. ### Impact Assessment If paired with a browser exploit, the disabled sandbox may enable compromise of the service account and access to its files, environment, network privileges, and other local resources. The ultimate scope depends on the operating-system privileges assigned to the Node.js process and any external container or mandatory access controls. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--no-sandbox` and `--disable-setuid-sandbox`. 2. Configure the deployment environment so Chromium's supported sandbox can operate correctly. 3. Run the service as a dedicated, non-root user with minimal filesystem and network permissions. 4. Isolate the process in a hardened container or virtual machine with a read-only filesystem where practical. 5. Apply seccomp, AppArmor, SELinux, or an equivalent mandatory access-control profile. 6. Keep Puppeteer and its associated Chromium build current with security updates. 7. Restrict navigation to approved destinations to reduce exposure to hostile browser content. 8. Avoid exposing the browser's remote debugging port outside the isolated runtime environment. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
server.js:94
Finding
Browser Input Including Credentials Is Logged in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `server.js:68-71`, `server.js:94-96` **Vulnerability Type**: Sensitive information exposure through application logging **Risk Level**: Medium ### Vulnerable Code ```js case 'type': if (!wsPage) throw new Error('没有活动的页面'); await wsPage.type(params.selector, params.text, { delay: params.delay || 50 }); return { success: true, action: 'type', target: params.selector, text: params.text }; ``` ```js const { action, params, id } = JSON.parse(message); console.log(`⚡ 收到指令:${action}`, params); ``` ### Technical Analysis The message handler logs the complete `params` object for every request. For the `type` action, `params.text` contains the exact text entered into the browser. This can include passwords, one-time codes, API keys, personal information, private messages, or other form data. The `type` handler also returns the entered text in its response object, unnecessarily duplicating sensitive input and increasing the number of places where it may be captured by clients, proxies, diagnostics, or surrounding infrastructure. ### Attack Path 1. A legitimate user or automation client sends a `type` command containing a password or other secret. 2. The server writes the complete parameters, including `params.text`, to standard output. 3. A process supervisor, container platform, terminal capture system, or centralized logging service stores the output. 4. An operator or attacker with log-reading access retrieves the secret. 5. The exposed credential or token may be reused against the affected account or service. ### Impact Assessment The issue exposes all text entered through the API to parties that can access process logs. Potentially affected data includes account passwords, authentication codes, tokens, payment details, and private form content. The resulting privileges depend on the captured secret and may include compromise of external accounts or disclosure of personal information. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not log complete request parameter objects. 2. Log only non-sensitive metadata such as the request ID, action name, result status, and processing duration. 3. Apply centralized field-based redaction for names such as `text`, `password`, `token`, `secret`, `cookie`, and `authorization`. 4. Do not include `params.text` in the response from the `type` action. 5. Restrict access to runtime and centralized logs using least privilege. 6. Configure short, documented retention periods and encryption for logs at rest and in transit. 7. Review existing retained logs and remove or rotate any credentials that may already have been captured. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill documentation omits or understates high-risk functionality such as arbitrary page-script execution via `evaluate`, while also overstating support for configurable headless/headful modes and auto-reconnect. Undisclosed script execution is especially risky because it can inspect page state, manipulate authenticated sessions, and trigger sensitive actions in the browser context.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill documentation omits or understates high-risk functionality such as arbitrary page-script execution via `evaluate`, while also overstating support for configurable headless/headful modes and auto-reconnect. Undisclosed script execution is especially risky because it can inspect page state, manipulate authenticated sessions, and trigger sensitive actions in the browser context.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The WebSocket API exposes an 'evaluate' action that passes attacker-controlled JavaScript directly into page.evaluate(), allowing any connected client to execute arbitrary code in the browser context of whatever page is open. In this skill, that can read DOM contents, interact with authenticated sessions, and trigger privileged actions on sites the browser has loaded, which is broader and riskier than normal fixed-function browser automation.

Missing User Warnings

High
Confidence
98% confidence
Finding
WebSocket messages can invoke arbitrary page script execution with no authentication, consent prompt, or user-facing warning. In a real browser context, this allows a connected client to silently inspect content, manipulate pages, and perform actions using any active authenticated session in the browser.

Lp3

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding
The skill exposes browser automation capabilities and references environment-variable configuration, but it does not declare any explicit tool scope or permission boundaries. In practice, this makes the effective authority of the skill ambiguous and increases the risk that an agent or user will invoke it with broader access than intended.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill describes screenshot, DOM extraction, navigation, and script execution, but does not warn that these operations can access sensitive page contents such as tokens, personal data, or authenticated account information. In a browser-automation context, absence of privacy guidance materially increases the chance of accidental collection or exposure of sensitive data.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Automated navigation, clicking, typing, and script execution can perform real actions on websites, including submissions, purchases, account changes, or destructive operations, yet the documentation does not warn about these consequences. In this context, the skill controls a real browser rather than a simulator, so unintended actions can have immediate external effects.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
All natural-language comments and console messages are in Chinese, including the instruction telling the user to respond with `已登录`. This imposes a specific language on users without documenting a locale restriction or providing an opt-in/alternative, which matches the stated language/locale policy violation category.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The manifest describes a generic browser automation skill that supports navigation, clicking, input, screenshots, and DOM retrieval via WebSocket control. This file instead hard-codes navigation to a specific third-party site (`fanqie.baidu.com/writer`) and is oriented toward checking login/publishing workflow state, which is narrower and different from the claimed general-purpose browser controller.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The file's human-facing comments and runtime messages are written in Chinese, and there is no indication that language selection is configurable or that the skill is intentionally region-specific. Under the stated policy, forcing a specific language without user opt-in is a locale-policy concern.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Launching Chromium with '--remote-debugging-port=9222' opens an additional browser control interface outside the documented WebSocket API. If that port is reachable by other local or network actors, they may bypass application logic entirely and gain full browser inspection/control, including page contents, cookies, and automation commands.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The snapshot action collects and returns current values from input and textarea elements, which can expose typed secrets such as usernames, personal data, search queries, or even passwords if pages misuse input types. Because this happens remotely over the WebSocket API without notice or consent, a client can silently harvest sensitive form data from any loaded page.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The description and changelog force a single language presentation, and the rest of the skill documentation continues in Chinese with no opt-in or note that the skill is intended only for Chinese-speaking users. Under the language/locale policy, a fixed language without user choice or explicit justification is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The manifest description is written only in Chinese ("AI 可控的 WebSocket 浏览器,基于 Puppeteer"), which can indicate a language-specific skill presentation without any stated user opt-in or documented locale constraint. Under the policy rule, language-specific behavior or presentation should either offer user choice or clearly justify the locale restriction.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"install-deps": "npm install puppeteer ws"
  },
  "dependencies": {
    "puppeteer": "^21.0.0",
    "ws": "^8.14.0"
  }
}
Confidence
87% confidence
Finding
Using a caret range for puppeteer allows future installs to resolve to different versions than were originally tested, which weakens build reproducibility and can silently introduce vulnerable or breaking releases. In a browser-automation skill that controls a real Chromium instance, dependency drift is more sensitive because security posture depends heavily on the exact browser automation stack shipped.

Unverifiable Dependency: puppeteer has 1 known advisory(ies) (CVE-2019-5786 (Use-After-Free in puppeteer)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "puppeteer": "^21.0.0",
    "ws": "^8.14.0"
  }
}
Confidence
93% confidence
Finding
Using a caret range for ws permits automatic resolution to newer minor/patch releases at install time, reducing reproducibility and making it unclear which security fixes or regressions are actually deployed. Because this skill exposes browser control over WebSocket, weaknesses in the WebSocket library have direct relevance to the attack surface and could amplify denial-of-service or memory disclosure risks if an affected version is installed.

Unverifiable Dependency: ws has 7 known advisory(ies) (CVE-2016-10518 (Remote Memory Disclosure in ws); CVE-2024-37890 (ws affected by a DoS when handling a request with many HTTP headers); CVE-2026-45736 (ws: Uninitialized memory disclosure) +4 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding
The manifest does not pin ws, and the package has a substantial advisory history including denial-of-service and memory disclosure classes of issues. Given this skill's core design relies on WebSocket-based remote browser control, uncertainty about the exact ws version materially increases risk because a vulnerable resolution would sit directly on the exposed communication path.

Description-Behavior Mismatch

Low
Confidence
81% confidence
Finding
The manifest emphasizes WebSocket real-time browser control and automatic reconnection as distinguishing features. In this file, the code attaches to an already running Chrome instance via `browserURL: 'http://127.0.0.1:9222'`, with no explicit WebSocket handling or reconnection logic present, so the documented behavior is only partially reflected here.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The script silently writes a screenshot of a logged-in browser session to a local file, which may capture sensitive account data, drafts, cookies-linked session state visible on screen, or other private content. In a browser automation skill, undisclosed artifact creation increases privacy and data-handling risk, especially when targeting an authenticated creator backend.

Static analysis

No suspicious patterns detected.