Back to skill

Security audit

Midea Cloud Control

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but it stores a Midea account password locally in plaintext and passes it through command-line arguments.

Review this skill before installing if you use a real Midea account. It may work for device control, but it saves your Midea password in a local JSON file and places the password in a process command line during setup. Prefer a version that uses an OS credential manager, enforces 0600-style file permissions, avoids command-line secrets, and documents how to delete saved credentials.

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

T09 · Insecure Skill Coding Practices

Error
Location
references/generated-config-store.md:25
Finding
Midea Cloud Credentials Are Persisted in Plaintext with Unrestricted Default File Permissions## Vulnerability Details **File Location**: `references/generated-config-store.md:25-28` and `references/generated-midea-skill-cli.md:62-67` **Vulnerability Type**: Plaintext sensitive-data storage **Risk Level**: High ### Vulnerable Code `references/generated-config-store.md:25-28`: ```python def save_config(data: dict[str, Any]) -> Path: ensure_dir() CONFIG_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") return CONFIG_PATH ``` `references/generated-midea-skill-cli.md:62-67`: ```python path = save_config({ "account": account, "password": password, "cloud_name": cloud_name, "devices": devices, }) ``` ### Technical Analysis The generated CLI passes the user's Midea account and password directly to `save_config()`. The configuration store serializes the complete dictionary into unencrypted JSON at `~/.openclaw/midea-cloud-control/config.json`. The file is written using `Path.write_text()` without explicitly enforcing owner-only permissions. Its effective permissions therefore depend on the host's umask and any permissions already present on the file. In a shared, misconfigured, backed-up, or compromised environment, another local principal or process may be able to read the password. Encryption at rest alone would not prevent access by a process running as the same user. An operating-system credential manager or dedicated secret service is the preferred storage mechanism. ### Attack Path 1. A user invokes the account connection workflow and supplies valid Midea credentials. 2. `connect()` creates a configuration dictionary containing the plaintext account and password. 3. `save_config()` serializes that dictionary to `~/.openclaw/midea-cloud-control/config.json`. 4. A local process, another user permitted by the resulting filesystem permissions, a backup reader, or malware running in the user's context reads the ...[truncated 672 chars]
Remediation
## Remediation Suggestions 1. Store the password in the operating system's credential manager, keyring, or another dedicated secret-management service. Persist only a credential reference in `config.json`. 2. If file-based storage is unavoidable, create `~/.openclaw/midea-cloud-control` with mode `0700` and atomically create the configuration file with mode `0600`. 3. Validate and correct permissions on an existing directory and file before reading or updating credentials. 4. Avoid following symbolic links when creating or replacing the configuration file, and use an atomic temporary-file-and-rename operation in the same protected directory. 5. Document how users can delete the cached secret and revoke or rotate credentials after suspected exposure. 6. Minimize retained data and avoid storing the password when a renewable token or similarly scoped credential is supported.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:53
Finding
Password Is Supplied Through a Command-Line Argument## Vulnerability Details **File Location**: `SKILL.md:53-55` **Vulnerability Type**: Credential exposure through process arguments and execution logs **Risk Level**: Medium ### Vulnerable Code ```powershell uv run python skills_runtime/midea-cloud-control/midea_skill_cli.py connect --account "<ACCOUNT>" --password "<PASSWORD>" ``` The corresponding generated argument parser is located at `references/generated-midea-skill-cli.md:154-165`: ```python async def main() -> int: parser = argparse.ArgumentParser(description="Unified CLI for the midea-cloud-control skill.") sub = parser.add_subparsers(dest="cmd", required=True) p_connect = sub.add_parser("connect") p_connect.add_argument("--account", required=True) p_connect.add_argument("--password", required=True) sub.add_parser("list") p_toggle = sub.add_parser("toggle") p_toggle.add_argument("--device-name", required=True) p_toggle.add_argument("--power", required=True, choices=["on", "off"]) ``` ### Technical Analysis The documented workflow requires the agent to interpolate the plaintext password into the command line. Command-line arguments may be observable through process-inspection facilities while the process is running. Depending on the execution environment, the complete command may also be retained in shell history, agent tool-call records, orchestration telemetry, diagnostic output, or audit logs. The instruction not to echo passwords in normal chat responses does not protect process metadata or execution logs. An attacker does not need to modify the command or exploit argument parsing; access to a process listing or retained command record may be sufficient. ### Attack Path 1. The user supplies a Midea account password to the agent. 2. The agent substitutes the password into the documented `--password` argument. 3. The runtime launches the process with the plaintext password in its argument ve ...[truncated 734 chars]
Remediation
## Remediation Suggestions 1. Remove the `--password` command-line option. 2. Read the password interactively with Python's `getpass.getpass()` when a terminal is available. 3. For noninteractive agent execution, pass the secret through a protected secret channel or an inherited file descriptor rather than the argument vector. 4. If standard input must be used, ensure it is supplied directly to the process and is not embedded in a shell command or logged by the orchestration layer. 5. Configure execution tooling to redact secrets from tool-call records, telemetry, error reports, and debug logs. 6. Ensure the password value is never included in exceptions, structured output, or diagnostic messages.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Missing User Warnings

High
Confidence
98% confidence
Finding
The code saves the user's Midea account and password in a local config file, and the skill description does not provide an explicit warning that credentials will be stored. Storing plaintext or recoverable credentials locally creates a significant compromise risk if the workspace, temp directory, logs, backups, or other local processes are accessible.

Session Persistence

Medium
Category
Rogue Agent
Content
This is a **pure-text publishable skill** for ClawHub.

The uploaded skill folder contains only Markdown/text files. When the skill is first used, OpenClaw should write local helper scripts from the code blocks stored in `references/generated-config-store.md` and `references/generated-midea-skill-cli.md`, then execute those local scripts.

Use this skill only for the **minimum verified workflow**:
- connect a user's Midea cloud account
Confidence
91% confidence
Finding
The skill instructs the agent to extract Python code from Markdown files, write that code to local helper scripts, and then execute those scripts. Treating text resources inside a skill package as executable code creates a code-generation/execution path that can run attacker-controlled content if the referenced Markdown is modified, substituted, or reviewed insufficiently, and it also establishes persistent local artifacts that survive the immediate session.

Session Persistence

Medium
Category
Rogue Agent
Content
## Known limitations
- Real-time state reads are not part of this skill.
- Temperature setting is not part of this skill.
- Some successful cloud write calls may print `null` via the library wrapper; treat physical device behavior as the source of truth.

## Local config file
This skill stores credentials and cached device metadata in:
Confidence
91% confidence
Finding
The file explicitly documents that the skill stores cloud credentials and cached device metadata in a persistent local config file under the user's home directory. Persisting authentication material on disk creates a real security risk if the file is readable by other local users, included in backups, exfiltrated by malware, or left unencrypted without clear lifecycle controls. The surrounding note about treating physical device behavior as the source of truth is not itself the vulnerability; the actual issue is long-term credential and device-data storage.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The markdown explicitly instructs the skill to write a Python file into the user's local workspace or a temporary directory on first use, but provides no user-facing warning or consent step. Silent local file creation is risky in an agent setting because it creates persistent artifacts and changes the user's environment beyond answering the immediate request.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The embedded code persists configuration under the user's home directory at ~/.openclaw/midea-cloud-control/config.json, again without any warning in the surrounding markdown. In this skill's context, the config is likely to contain Midea account and device information, so undisclosed persistence increases privacy and credential exposure risk if the host is shared, backed up, or later accessed by other tools.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs writing an executable Python file into the user's workspace or temp directory without an explicit user-facing warning or consent step. Even though the code appears related to the advertised functionality, silent local file creation expands the attack surface, can overwrite or plant executable content, and is risky because skill content must be treated as untrusted.

Static analysis

No suspicious patterns detected.