Back to skill

Security audit

automation browser

Security checks for vulnerabilities and agentic risk

Overview

This browser automation skill is mostly purpose-aligned, but it makes high-impact system changes and can expose typed browser input in logs.

Review this carefully before installing. Run the installer only if you trust the QQ Browser/x5use distribution source and are comfortable with system package and system Python changes. Avoid entering secrets through input_text.py unless logging is fixed, and know how to stop the X5 background service and clean /usr/local/qb_logs.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Error
Location
scripts/install_dep.sh:27
Finding

Remote executable packages are installed without explicit integrity verification

Content
View full analysis

Vulnerability Details

File Location: scripts/install_dep.sh:27-31, 57-58
Vulnerability Type: Supply-chain integrity weakness
Risk Level: High

Vulnerable Code

bash
curl -fSL -o "$TMP_DIR/$QB_DEB" "${BASE_URL}/${QB_DEB}"
dpkg -i "$TMP_DIR/$QB_DEB" || apt-get install -f -y
bash
curl -fSL -o "$TMP_DIR/$QB_RPM" "${BASE_URL}/${QB_RPM}"
yum install -y "$TMP_DIR/$QB_RPM"
bash
curl -fSL -o "$TMP_DIR/$X5USE_WHL" "${BASE_URL}/${X5USE_WHL}"
pip3 install --break-system-packages --ignore-installed "$TMP_DIR/$X5USE_WHL"

Technical Analysis

The installation script downloads native browser packages and a Python wheel from an external HTTPS server and immediately installs them. Although HTTPS protects the transfer in transit, the script does not verify pinned cryptographic hashes, a signed manifest, or an explicitly trusted package signature before installation.

Package installation is a code-execution boundary. Native package installation can execute package-maintainer scripts, while Python package installation may execute build or installation logic. The use of --break-system-packages and --ignore-installed also permits the wheel to modify the system Python environment and replace existing packages rather than remaining isolated.

The artifact filenames are versioned, which improves reproducibility, but filenames alone do not establish integrity. This finding does not prove that the current hosted packages are malicious; it establishes that compromise or unauthorized replacement of those packages would not be detected by this script.

Attack Path

  1. An attacker compromises the external distribution account, server, publication pipeline, or hosted artifact.
  2. The attacker replaces one of the expected .deb, .rpm, or .whl files while retaining its expected filename.
  3. A user runs the documented scripts/install_dep.sh command.
  4. curl downloads the substituted artifact successfully over HTTPS.
  5. Because no p ...[truncated 777 chars]
Remediation
View remediation

Remediation Suggestions

  1. Publish a SHA-256 or stronger digest for every downloaded artifact in a trusted, version-controlled file distributed with the Skill.
  2. Verify each artifact before invoking dpkg, yum, or pip3, and terminate installation on any mismatch.
  3. Prefer vendor-signed package repositories and ensure package-manager signature verification remains enabled.
  4. For directly distributed artifacts, verify detached signatures against a pinned vendor public key.
  5. Pin immutable artifact versions and avoid mutable download paths.
  6. Install the Python wheel in a dedicated virtual environment rather than using --break-system-packages.
  7. Remove --ignore-installed unless replacement of installed packages is explicitly required and reviewed.
  8. Generate and retain a dependency inventory or software bill of materials for the browser package and wheel.
  9. Run installation with the minimum privileges required and separate package acquisition from privileged installation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/input_text.py:19
Finding

Browser input values are disclosed through plaintext logging

Content
View full analysis

Vulnerability Details

File Location: scripts/input_text.py:19-29
Vulnerability Type: Plaintext exposure of potentially sensitive input
Risk Level: Medium

Vulnerable Code

python
index = int(sys.argv[1])
text = sys.argv[2]
args = {"index": index, "text": text}
if len(sys.argv) > 3:
    args["xpath"] = sys.argv[3]

client = MCPClient()
try:
    await client.initialize()
    logging.info(f"正在调用 browser_input_text,目标索引: {index},文本: {text}")
    result = await client.call_tool("browser_input_text", args)

Technical Analysis

The script accepts arbitrary browser form content in sys.argv[2] and logs the full value at INFO level before sending it to the browser tool. Browser input can include passwords, session tokens, API keys, personal information, payment data, or other confidential values.

The logging configuration in scripts/mcp_client.py sends INFO messages to standard output. Consequently, the input may be retained in terminal history captures, agent execution transcripts, orchestration logs, CI logs, or centralized log systems. The value is also supplied as a command-line argument, which may make it temporarily visible to local process-list inspection, depending on the operating system and process permissions.

This issue does not independently obtain secrets. It exposes secrets whenever a caller legitimately uses this generic input function to enter sensitive content.

Attack Path

  1. A user or automation workflow invokes input_text.py to enter a sensitive value into a browser form.
  2. The value is passed through the process command line as sys.argv[2].
  3. The script interpolates the complete value into an INFO log message.
  4. Standard output or an execution transcript records the log entry.
  5. A user, process, monitoring system, or log collector with access to those records retrieves the sensitive value.

A local observer with sufficient process-inspection permission may also read the argument while the process is ...[truncated 641 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the input value from all log messages. Log only non-sensitive metadata, such as the target element index.
  2. Use a fixed redaction marker, for example:
python
logging.info("Calling browser_input_text for index %s; text=[REDACTED]", index)
  1. Avoid passing secrets through command-line arguments. Accept sensitive values through standard input, a protected file descriptor, or an approved secret-management interface.
  2. Ensure exception handling and tool-result printing do not echo submitted form values.
  3. Apply centralized log redaction as defense in depth, but do not rely on it instead of source-level redaction.
  4. Restrict access to execution logs and configure an appropriate retention period.
  5. Add automated tests that submit sentinel secret values and verify that they do not appear in stdout, stderr, tracebacks, or persistent logs.
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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill description omits that it starts a local background service, performs port checks, and writes logs to local filesystem paths such as /usr/local/qb_logs. Hidden process management and local writes increase risk because they persist beyond a single browser action, can interfere with the host, and may expose local services or sensitive data through logs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description omits that it starts a local background service, performs port checks, and writes logs to local filesystem paths such as /usr/local/qb_logs. Hidden process management and local writes increase risk because they persist beyond a single browser action, can interfere with the host, and may expose local services or sensitive data through logs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill exposes capabilities that imply shell execution, network access, file writes, and service control, but it declares no explicit tool scope or permission boundaries. In a browser-automation skill, this is dangerous because callers may assume limited browser actions while the documented setup/install commands can modify the host and access external resources.

Content

No source excerpt is available for this finding.

Context Window Stuffing

Medium
Category
Memory Poisoning
Confidence
85% confidence
Finding

Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.

Content

Scanner excerpt · SKILL.md (reported line 38)May include surrounding context.

Element interaction

bash
python3 skills/qb-x5-use/scripts/click_element.py <index> [xpath]      # Click element by index
python3 skills/qb-x5-use/scripts/input_text.py <index> <text> [xpath]  # Fill input by index
python3 skills/qb-x5-use/scripts/get_dropdown_options.py <index>       # Get dropdown options
python3 skills/qb-x5-use/scripts/select_dropdown_option.py <index> <text>  # Select dropdown option

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill advertises file downloading but does not warn that downloads write data to the local system or explain where files are stored. In a web-automation context, this is risky because an agent could be induced to fetch untrusted content, consume disk space, or place executable or sensitive files on the host without clear user awareness.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This script includes natural-language strings that force a specific language for usage instructions and behavior description. Under the policy, language constraints should be optional or clearly justified; here there is no opt-in, fallback, or documentation indicating the skill is intentionally Chinese-only.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The docstring and command-line usage messages are written only in Chinese, which imposes a specific language on users without any visible opt-in or explanation that the skill is intended solely for a Chinese-speaking environment. This matches the policy category for language or locale constraints that are not optional or justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script prints all usage instructions and parameter descriptions in Chinese, which imposes a specific language on users. Under the policy, language constraints should either be optional for the user or clearly documented as a justified locale-specific requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code contains only Chinese natural-language strings in the docstring and log/error messages, which imposes a specific language on users and operators. The file provides no indication that language selection is optional or configurable, so it may violate a language/locale policy requiring user choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script logs the full user-supplied text before submitting it to the browser, which can expose secrets such as passwords, tokens, personal data, or prompts in log files. In a browser automation skill, this is more dangerous because the entered text is often credential or form data, and logs may be retained, aggregated, or viewed by operators beyond the original user.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script automatically installs a downloaded system package and, on Debian-based systems, invokes dependency repair with 'apt-get install -f -y' without any explicit consent, warning, or package integrity verification. In a skill installer, this is security-relevant because it makes privileged changes to the host system and trusts a remote binary source, increasing the blast radius if the package source is compromised or the script is run unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script installs a Python wheel directly into the system environment using pip3 with '--break-system-packages' and '--ignore-installed', which can overwrite or bypass package management protections. This is dangerous because it can destabilize the host Python environment and installs a remotely downloaded artifact without integrity validation, especially risky for an automation skill that may be installed broadly on user machines.

Content

No source excerpt is available for this finding.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · scripts/mcp_client.py (reported line 33)May include surrounding context.

python
def _is_mcp_service_running() -> bool:
    """Check if the MCP service is already running."""
    try:
        req = urllib.request.Request(f"http://localhost:{MCP_PORT}/sse", method="GET")
        urllib.request.urlopen(req, timeout=2)
        return True
    except Exception:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/mcp_client.py (reported line 64)May include surrounding context.

python
# Start the MCP service in background
    logging.info(f"Starting X5 MCP service on port {MCP_PORT}...")
    with open(LOG_FILE, "a") as log_f:
        proc = subprocess.Popen(
            [MCP_CMD, "--transport", "sse", "--port", str(MCP_PORT), "--log-dir", LOG_DIR],
            stdout=log_f,
            stderr=subprocess.STDOUT,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file's natural-language strings are exclusively in Chinese, including the docstring and user-facing log/error messages. That creates a locale/language constraint without any visible opt-in, fallback, or documentation justifying a region-specific requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The docstring and command-line usage/help text are written only in Chinese, which imposes a specific language on users without any opt-in or alternative. The policy explicitly calls out language or locale constraints as violations unless the skill offers choice or clearly documents a justified regional scope.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/click_element.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/click_video_button.py (reported line 7)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/download_file.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/download_print.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/download_url.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/download_video.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/download_videos.py (reported line 7)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/get_content.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/get_dropdown_options.py (reported line 6)May include surrounding context.

python
import sys
import traceback

sys.path.insert(0, __import__('os').path.dirname(__import__('os').path.abspath(__file__)))
from mcp_client import MCPClient

# 默认等待秒数

Static analysis

No suspicious patterns detected.