Back to skill

Security audit

android-auto-controller

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned for Android automation, but it needs Review because it can control a real phone and send full screen images plus task goals to a configurable VLM service without strong safeguards.

Install only if you intentionally want an agent to control a real Android phone. Use a trusted local or HTTPS VLM endpoint, avoid showing sensitive notifications or apps during automation, require your own confirmation before messages, purchases, or account changes, and clean up retained screenshot files. Prefer pinned dependencies and an isolated environment.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/android_agent.py:88
Finding
Potentially Sensitive Android Screenshots Can Be Sent over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/android_agent.py:15`, `scripts/android_agent.py:88-124`, and `scripts/android_agent.py:147-194` **Vulnerability Type**: Insecure transmission of sensitive screen data **Risk Level**: High ### Vulnerable Code ```python VLM_BASE_URL = os.getenv("VLM_BASE_URL", "http://127.0.0.1:13009/v1") ``` ```python img_path = "vlm_temp_vision.jpg" d.screenshot(img_path) with open(img_path, "rb") as f: base64_img = base64.b64encode(f.read()).decode('utf-8') client = OpenAI(api_key=VLM_API_KEY, base_url=VLM_BASE_URL) response = client.chat.completions.create( model=VLM_MODEL_NAME, messages=[ {"role": "user", "content": [ {"type": "text", "text": prompt}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_img}"}} ]} ], temperature=0, response_format={"type": "json_object"} ) ``` The same behavior is present in the planning function: ```python img_path = "vlm_plan_vision.jpg" d.screenshot(img_path) with open(img_path, "rb") as f: base64_img = base64.b64encode(f.read()).decode('utf-8') client = OpenAI(api_key=VLM_API_KEY, base_url=VLM_BASE_URL) response = client.chat.completions.create( model=VLM_MODEL_NAME, messages=[ {"role": "user", "content": [ {"type": "text", "text": prompt}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_img}"}} ]} ], temperature=0, response_format={"type": "json_object"} ) ``` ### Technical Analysis The Skill captures the entire Android screen and includes the image in an OpenAI-compatible API request. Android screenshots can contain highly sensitive information, including private messages, contact names, account balances, authentication codes, email addresses, notification contents, and information from unrelated applications. Base64 encoding is required to embed the image in a data URL, but it does no ...[truncated 2229 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS for every non-loopback VLM endpoint. 2. Reject unsupported URL schemes and validate the endpoint before creating the client. 3. Permit plaintext HTTP only for explicit loopback addresses such as `127.0.0.1`, `::1`, and `localhost`. 4. Consider maintaining an administrator-approved endpoint allowlist. 5. Clearly notify users that complete screenshots and task descriptions are sent to the configured VLM service. 6. Obtain explicit consent before using a remote model with screen data. 7. Redact notification areas, password fields, one-time codes, and other sensitive regions where technically possible. 8. Prefer local VLM processing for sensitive workflows. 9. Add certificate verification guidance and prohibit disabling TLS verification. 10. Minimize captures by taking screenshots only when required for the requested action. 11. Add tests confirming that remote `http://` URLs are rejected. Example validation logic should parse the URL, verify its scheme and hostname, and fail closed when a non-loopback host does not use HTTPS. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/android_agent.py:88
Finding
Sensitive Screenshots Persist in Predictable Working-Directory Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/android_agent.py:88-92` and `scripts/android_agent.py:147-151` **Vulnerability Type**: Unsafe temporary-file handling and sensitive-data retention **Risk Level**: Medium ### Vulnerable Code ```python img_path = "vlm_temp_vision.jpg" d.screenshot(img_path) with open(img_path, "rb") as f: base64_img = base64.b64encode(f.read()).decode('utf-8') ``` ```python img_path = "vlm_plan_vision.jpg" d.screenshot(img_path) with open(img_path, "rb") as f: base64_img = base64.b64encode(f.read()).decode('utf-8') ``` ### Technical Analysis The Skill stores complete Android screenshots under fixed, predictable filenames in its current working directory. Neither function removes the image after reading it, including after successful API submission or an exception. Consequently, the most recent screenshots can remain on disk indefinitely. Their permissions depend on the current process environment and operating-system defaults rather than an explicit restrictive policy. Fixed filenames also allow unrelated local processes with access to the working directory to locate the files without searching for randomized temporary names. The files are overwritten on later runs, but overwriting does not provide reliable secure deletion and does not protect the files between invocations. They may also be collected by backup systems, workspace archiving, debugging tools, or artifact-upload processes. ### Attack Path 1. The Skill runs while private content is visible on the Android device. 2. `d.screenshot()` writes the full screen to `vlm_temp_vision.jpg` or `vlm_plan_vision.jpg`. 3. The Skill reads the image but does not delete it. 4. A local process, another user with filesystem access, a backup service, or an artifact collector finds the predictable filename. 5. That party copies or uploads the retained screenshot and obtains the displayed sensitive information. If the VLM call raises an exception, the same ret ...[truncated 539 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer obtaining screenshot bytes directly in memory if supported by `uiautomator2`. 2. If a file is necessary, use Python's `tempfile` module to create a unique file with restrictive permissions. 3. Delete the file in a `finally` block so cleanup occurs after both successful requests and exceptions. 4. Store temporary images in an operating-system temporary directory rather than the project or current working directory. 5. Explicitly restrict file permissions to the current user. 6. Avoid logging temporary paths or image contents. 7. Document the screenshot retention policy and ensure that no image is retained after processing. 8. Review workspace backup and artifact-upload configuration to exclude temporary screen captures. 9. Add automated tests that verify screenshot files are removed when API calls succeed, fail, or time out. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:18
Finding
Third-Party Python Dependencies Are Installed without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:18` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Low ### Vulnerable Code ```bash pip install uiautomator2 openai ``` ### Technical Analysis The installation instructions retrieve the latest available versions of `uiautomator2`, `openai`, and their transitive dependencies without version constraints or cryptographic hashes. The reviewed package names are established names and do not appear to be typographical imitations, and the instructions do not specify a suspicious custom package index. However, an unpinned installation is not reproducible. A future compromised release, malicious transitive dependency, or incompatible update would be installed automatically. Python packages can execute code during installation and later execute with the privileges of the OpenClaw process when imported. The audit found no evidence that this Skill intentionally retrieves a malicious package. The risk arises from unsafe dependency management rather than a confirmed malicious dependency. ### Attack Path 1. A direct or transitive dependency publishes a compromised release, or its distribution account or build pipeline is compromised. 2. A user follows the documented unpinned `pip install` command after the compromised release becomes current. 3. `pip` downloads and installs the affected package. 4. Malicious code executes during installation or when `android_agent.py` imports the dependency. 5. The malicious package gains access to the privileges and data available to the installing user or OpenClaw process, potentially including environment variables and connected-device access. This path depends on an upstream supply-chain compromise; none was observed in the audited project itself. ### Impact Assessment A compromised dependency could execute arbitrary code with the privileges of the user installing or running the Skill. Depending on the runtime environment, this could expose ...[truncated 322 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a reviewed requirements or lock file with exact dependency versions. 2. Pin transitive dependencies using a reproducible dependency-management tool. 3. Generate and verify cryptographic hashes, such as with `pip install --require-hashes`. 4. Install packages only from an approved package index over HTTPS. 5. Review dependency release notes and security advisories before updating pins. 6. Use an isolated virtual environment with only the permissions needed by the Skill. 7. Run software composition analysis and vulnerability scanning in CI. 8. Update dependencies through a controlled review process rather than retrieving mutable latest versions during installation. ]]>
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
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The manifest and description materially understate or misrepresent behavior: the skill can perform real actions on a physical phone, access device/app state, and send screenshots to an external VLM endpoint, while claiming stricter guarantees than are actually enforceable. This is dangerous because users and upstream agents may trust false safety claims and authorize actions or data exposure they would not otherwise permit.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
---
name: android-auto-controller
description: "控制 Android 手机的终极工具。具备视觉状态感知、自动关闭干扰弹窗、模拟人手操作的能力。内置严格的反幻觉校验机制和防绕过限制,以真实的屏幕视觉反馈为唯一判断标准。"
metadata: {"openclaw":{"emoji":"📱","requires":{"bins":["python3"],"env":["VLM_API_KEY","VLM_BASE_URL","VLM_MODEL_NAME","VLM_COORD_SCALE"]},"primaryEnv":"VLM_API_KEY"}}
---

# 📱 Android Auto Controller (安卓视觉自动化控制)

> **🧑‍💻 以下内容为人类用户阅读的安装与配置指南**

这是一个为 OpenClaw �
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill declares environment requirements and enables code-driven device control, but does not define explicit tool scope such as allowed tools or permissions. In an agent setting, missing scope boundaries can let the model invoke this high-impact skill more freely than intended, especially since it can control a real connected phone and interact with external services via environment-provided VLM credentials.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The user-facing description does not clearly warn that the skill can execute irreversible actions on a real physical phone, including opening apps, entering text, and sending messages. In this context, inadequate disclosure is dangerous because users may invoke the skill without understanding that it can affect live accounts, contacts, and private data on a connected device.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The activation condition is overly broad ('when the user asks to operate the phone'), making accidental or unnecessary invocation likely for general phone-related requests. Because this skill performs real-world actions on a connected device, broad triggering increases the risk of unintended app launches, taps, text entry, or message sending.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The function captures a live device screenshot, encodes it, and sends it to a configurable remote VLM endpoint for UI interpretation. Because phone screens commonly contain messages, contacts, tokens, notifications, and other sensitive data, this creates a real confidentiality risk, especially since the default is an HTTP localhost endpoint and the base URL can be redirected elsewhere without any user-facing consent or trust validation.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The code transmits screenshot data to a remote model call without any explicit warning or consent flow at the point of collection. Even if remote analysis is intended, the absence of transparent disclosure materially increases privacy risk because users may reasonably assume the automation is analyzing the screen locally.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The planning routine sends both a screenshot and the user's high-level goal to an external VLM service, exposing not just visual screen contents but also user intent. In the context of an Android controller, this can reveal private app usage, personal workflows, contacts, financial activity, or other sensitive behavioral data to a third party beyond the stated local phone-control function.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This planning call uploads both screen contents and the user's goal text without clear disclosure, combining two sensitive data sources into a single remote request. In an automation tool with broad device control, that combination can expose especially revealing personal or operational context, making the privacy impact stronger than a screenshot-only upload.

Static analysis

No suspicious patterns detected.