Back to skill

Security audit

千问浏览器原生 CDP 驱动

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly for Qianwen browser automation, but it uses a real logged-in browser profile and can leave a persistent local debugging interface enabled.

Install only if you intentionally want automation against an authenticated Qianwen profile. Prefer a dedicated automation profile, avoid applying the shortcut patch unless you understand that it can leave CDP enabled across browser launches, and require explicit user confirmation before running eval, launch, relaunch, posting, form submission, deletion, or other account-impacting actions.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
patch_lnk.py:18
Finding
Persistent Unauthenticated CDP Access to the User's Authenticated Browser Profile<![CDATA[ ## Vulnerability Details **File Location**: `patch_lnk.py:18-26`, `patch_lnk.py:91-103`, `qw.cjs:47-48`, `qw.cjs:168-172` **Vulnerability Type**: Persistent exposure of a privileged browser debugging interface **Risk Level**: High ### Vulnerable Code ```python PORT_ARG = "--remote-debugging-port=9666" # Four Qianwen shortcuts: Start Menu, Desktop, Taskbar, and Quick Launch LNK_PATHS = [ os.path.expandvars(r"%APPDATA%\Microsoft\Windows\Start Menu\Programs\千问.lnk"), os.path.expandvars(r"%USERPROFILE%\Desktop\常用软件\千问.lnk"), os.path.expandvars(r"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\千问.lnk"), os.path.expandvars(r"%APPDATA%\Microsoft\Internet Explorer\Quick Launch\千问.lnk"), ] ``` ```python new_args = (old_args + " " + PORT_ARG).strip() new_length = len(new_args) + 1 # includes null new_bytes = struct.pack("<H", new_length) + (new_args + "\x00").encode("utf-16-le") info = {"path": path, "old_args": old_args, "new_args": new_args, "old_len": a_end - a_start, "new_len": len(new_bytes)} if apply: new_data = data[:a_start] + new_bytes + data[a_end:] with open(path, "wb") as f: f.write(new_data) info["status"] = "PATCHED" ``` ```javascript const QW_PROFILE = process.env.QW_PROFILE || path.join(HOME, 'AppData', 'Local', 'Qianwen', 'User Data'); const CDP_PORT = Number(process.env.QW_CDP_PORT) || 9666; ``` ```javascript const child = spawn(QW_EXE, [ '--remote-debugging-port=' + CDP_PORT, '--user-data-dir=' + QW_PROFILE, '--no-first-run', '--no-default-browser-check', ], { detached: true, stdio: 'ignore' }); child.unref(); ``` ### Technical Analysis The shortcut patcher persistently adds `--remote-debugging-port=9666` to four user launch entries. Consequently, subsequent browser launches expose Chrome DevTools Protocol even when no active automation task requires it. The browser is also configured to use the user's real Qianwen profile. This profile may contain authentica ...[truncated 2070 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not modify persistent browser shortcuts by default. 2. Enable CDP only after explicit user authorization for a specific automation session. 3. Use a dedicated automation profile that does not contain the user's general-purpose authenticated sessions. 4. Select a random ephemeral port for each session instead of a fixed, predictable port. 5. Start the browser only for the duration of the requested operation and terminate it cleanly afterward. 6. Verify that the debugging port is closed when automation completes. 7. If the real profile is strictly required, display a clear warning that local processes can access the debugging interface. 8. Provide an automatic rollback mechanism that removes the debugging argument from every modified shortcut. 9. Restrict filesystem permissions on launch entries and relevant profile directories where possible. 10. Consider a broker process that authenticates and authorizes a limited set of browser operations instead of exposing unrestricted CDP. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
qw.cjs:195
Finding
Unrestricted Caller-Controlled JavaScript Execution in Authenticated Browser Pages<![CDATA[ ## Vulnerability Details **File Location**: `qw.cjs:195-201`, `qw.cjs:291` **Vulnerability Type**: Unrestricted page-context code execution **Risk Level**: Medium ### Vulnerable Code ```javascript async function evalJS(targetId, expr) { const tws = await getTargetWs(targetId); await cdp(tws, 'Runtime.enable'); const r = await cdpR(tws, 'Runtime.evaluate', { expression: expr, returnByValue: true }); tws.close(); return r; } ``` ```javascript case 'eval': out = await evalJS(args[0], args.slice(1).join(' ')); break; ``` ### Technical Analysis The `eval` command concatenates caller-provided command-line arguments and passes the resulting expression directly to CDP's `Runtime.evaluate`. No syntax restrictions, operation allowlist, origin validation, or confirmation boundary is applied. This is an advertised automation feature rather than concealed code execution. However, it gives the caller unrestricted page-context execution in browser targets that may carry the user's real authenticated sessions. Page-context JavaScript can read accessible DOM content, alter forms, invoke application APIs available to the page, and initiate authenticated operations. This design also increases prompt-injection risk in Agent-driven workflows. If untrusted webpage content can influence generated commands, the Agent may execute an expression that exceeds the user's intended task. ### Attack Path 1. The Agent processes an automation request or untrusted instructions obtained from webpage content. 2. The resulting command invokes `qw.cjs eval` with an attacker-influenced expression. 3. The script identifies the selected target and connects to its debugger WebSocket. 4. The expression is sent without validation through `Runtime.evaluate`. 5. The expression executes in the selected page context with access to that origin's authenticated state and DOM. 6. Sensitive page content is returned, page state is altered, or an authenticated action is initiated. ### I ...[truncated 616 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the unrestricted `eval` command from normal user-facing workflows. 2. Replace it with narrowly scoped operations implemented through fixed CDP calls. 3. If evaluation is essential, require explicit user confirmation immediately before execution. 4. Validate the target URL and origin against an allowlist appropriate to the requested task. 5. Reject expressions containing assignments, network calls, dynamic code construction, navigation, or other side effects unless separately authorized. 6. Separate read-only inspection from state-changing operations. 7. Use an isolated automation profile with minimal authenticated access. 8. Record the target origin and exact expression in an audit log without recording sensitive results. 9. Treat webpage-provided instructions as untrusted and prevent them from directly determining evaluation expressions. 10. Add policy checks for consequential actions such as posting, messaging, purchasing, deleting, or submitting forms. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
qw.cjs:30
Finding
Environment-Controlled Module Loading and Executable Launch<![CDATA[ ## Vulnerability Details **File Location**: `qw.cjs:30-46`, `qw.cjs:168-172` **Vulnerability Type**: Unsafe trust in environment-controlled code and executable paths **Risk Level**: Low ### Vulnerable Code ```javascript const WS_CANDIDATES = [ process.env.QW_WS_PATH, path.join(HOME, '.workbuddy', 'skills', 'xbrowser', 'scripts', 'src', 'node_modules', 'ws'), path.join(HOME, '.openclaw', 'tools', 'xbrowser', 'node_modules', 'ws'), ].filter(Boolean); let WebSocket = null; for (const p of WS_CANDIDATES) { try { WebSocket = require(p); break; } catch (e) { /* try next */ } } if (!WebSocket) { console.error('[qw] 找不到 ws 模块(已尝试:' + WS_CANDIDATES.join(' ; ') + ')'); console.error(' 安装含 ws 依赖的环境,或设置环境变量 QW_WS_PATH 指向 ws 模块目录后重试。'); process.exit(1); } const QW_EXE = process.env.QW_EXE || path.join(HOME, 'AppData', 'Local', 'Programs', 'QianwenApp', 'qianwen.exe'); ``` ```javascript const child = spawn(QW_EXE, [ '--remote-debugging-port=' + CDP_PORT, '--user-data-dir=' + QW_PROFILE, '--no-first-run', '--no-default-browser-check', ], { detached: true, stdio: 'ignore' }); child.unref(); ``` ### Technical Analysis `QW_WS_PATH` is accepted directly from the process environment and supplied to Node.js `require()`. Loading a CommonJS module executes its top-level code. Therefore, an attacker who can control this environment variable and place a malicious module at the referenced path can cause local JavaScript execution when the Skill starts. Similarly, `QW_EXE` determines the executable passed to `spawn()` by the `launch` operation. If an attacker controls the execution environment, this variable can point to a malicious local executable. This issue requires prior ability to influence the Skill's environment and, for module loading, provide an accessible malicious file. It does not independently create a remote execution path, which limits its severity. Nevertheless, it unnecessarily expands the trusted input boundary. ### Attack Pat ...[truncated 1102 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove environment-variable overrides from production deployments when they are not essential. 2. Resolve module and executable paths to canonical absolute paths before use. 3. Enforce strict allowlists of approved module directories and executable locations. 4. Reject paths outside trusted, administrator-controlled installation directories. 5. Verify file ownership and permissions before loading or launching a referenced file. 6. Prefer a declared, pinned `ws` package dependency rather than dynamically discovering modules from unrelated tool installations. 7. Validate that `QW_EXE` resolves to the expected signed Qianwen executable. 8. Sanitize the execution environment when the Skill is launched by an Agent or automation platform. 9. Fail closed when path validation fails instead of trying an untrusted candidate. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill’s stated purpose is browser automation, but the documentation also describes persistent modification of local Windows shortcut files to inject a remote debugging port into multiple launch paths. That materially expands behavior into host persistence and local file tampering, which is security-sensitive and not clearly disclosed as part of the core capability. In this context, it is especially risky because it enables long-lived CDP access to a real logged-in browser profile, increasing the chance of unauthorized account actions or data exposure.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The invocation description is broad enough to match many ordinary browser tasks, which can cause the skill to be selected in situations where a less-privileged or safer tool would suffice. Because this skill operates a real logged-in browser via CDP, overbroad triggering increases the likelihood of unnecessary access to sensitive sessions and unintended external actions.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation emphasizes using the user’s real logged-in profile for automation and content access, but it does not present a prominent upfront warning about privacy, session reuse, and account-impact risks. That omission is dangerous because users may not understand that the automation can read authenticated content, perform actions as them, and expose sensitive data from an existing profile.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The skill text repeatedly assumes operation against 'the boss' real logged-in profile and frames that as the default, rather than presenting a neutral, consent-based choice. This normalizes acting through another person’s authenticated session and can encourage automation that exceeds the actual operator’s authority, especially when combined with instructions to preserve login state and avoid disrupting the existing instance.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill is presented as browser automation, but its launch flow can terminate all running qianwen.exe processes and relaunch the browser against the user's real profile. That creates side effects beyond tab automation: it can disrupt active user sessions, risk profile corruption, and manipulate a privileged authenticated browser context without clear scoping or consent.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The eval command exposes arbitrary JavaScript execution inside any browser target created or attached by the tool. In the context of a real logged-in browser profile, this enables unrestricted reading/modification of page data, DOM scraping, triggering privileged actions on sites, and access to sensitive in-session content well beyond the advertised 'open/click/fill/screenshot' scope.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The inline comment describes a graceful close intended for a relaunch flow, implying the browser will be brought back up afterward. In reality, after `taskkill`, the code calls `ensureInstance()`, whose documented behavior is to refuse spawning and merely report that launch is needed if CDP is not already listening.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The relaunch path silently kills all running qianwen.exe processes without an in-band warning or confirmation. In a skill intended for ordinary browser automation, that can unexpectedly destroy user work, interrupt authenticated sessions, and facilitate covert takeover of the browser context under automation control.

Context-Inappropriate Capability

Low
Confidence
77% confidence
Finding
The skill's purpose is to drive Qianwen Browser via CDP, but the implementation inspects host environment variables (`QW_WS_PATH`, `QW_EXE`, `QW_PROFILE`, `QW_CDP_PORT`) and probes specific local directories for dependencies. While partly practical, this host-environment discovery is not expressed in the manifest and is not directly part of the user-facing browser automation purpose.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This function captures page content and persists it to a filesystem path, which affects user data/storage and may save sensitive page contents locally. The operation lacks a confirmation prompt or explicit runtime warning beyond the command name and inline code comments.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
qw.cjs:113