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.
