T09 · Insecure Skill Coding Practices
Warning
- Location
- express_monitor.py:25
- Finding
- Phone Numbers Stored in Plaintext Without Explicit Access Controls## Vulnerability Details **File Location**: `express_monitor.py:25-28` **Vulnerability Type**: Plaintext storage of sensitive personal data **Risk Level**: Medium ### Vulnerable Code ```python def save_phones(phones): """保存手机号""" with open(PHONE_FILE, 'w') as f: json.dump(phones, f, ensure_ascii=False, indent=2) ``` The destination is defined as follows: ```python DATA_DIR = os.path.expanduser("~/.openclaw/workspace/data/express") os.makedirs(DATA_DIR, exist_ok=True) PHONE_FILE = os.path.join(DATA_DIR, "phones.json") ``` ### Technical Analysis Bound phone numbers are serialized directly into `~/.openclaw/workspace/data/express/phones.json` as plaintext JSON. The application does not encrypt the data and does not explicitly enforce restrictive permissions on either the data directory or the resulting file. File accessibility therefore depends on the process environment and its effective `umask`. In an environment with permissive defaults, another local account or process with workspace access may be able to read the stored phone numbers. The data may also be exposed through workspace backups, support bundles, or accidental directory disclosure. This behavior contradicts the statement in `SKILL.md` that phone binding information is stored separately in encrypted form. Users may consequently provide personal data under an inaccurate security assumption. ### Attack Path 1. A user invokes the `bind` command with a valid phone number. 2. `bind_phone()` appends the number to the in-memory phone list. 3. `save_phones()` serializes the list into `phones.json` without encryption. 4. A local actor, compromised process, backup reader, or other party with access to the workspace reads or copies the JSON file. 5. The actor obtains every phone number bound through this skill. This attack requires local filesystem access or another mechanism that exposes the workspace; the code does not itself t ...[truncated 525 chars]
- Remediation
- ## Remediation Suggestions 1. Store phone numbers using operating-system-backed credential storage where available. 2. If file storage is required, encrypt the data with authenticated encryption and keep the encryption key outside the data file, preferably in a platform credential manager. 3. Create the data directory with mode `0700` and the phone file with mode `0600`. Do not rely solely on the ambient `umask`. 4. Use atomic writes through a securely created temporary file, set restrictive permissions before adding sensitive content, and then replace the destination file. 5. Minimize retained data and provide a command that lets users remove bound phone numbers. 6. Mask phone numbers when displaying them, such as `138****8000`, unless full disclosure is explicitly necessary. 7. Update `SKILL.md` so its storage claims accurately reflect the implementation, and do not claim encryption until authenticated encryption or secure credential storage is actually implemented. 8. Review existing installations and securely migrate or delete previously created plaintext `phones.json` files.
