T09 · Insecure Skill Coding Practices
Warning
- Location
- emotion_memory.py:14
- Finding
- Plaintext Persistence of Sensitive Conversation and Emotion Data## Vulnerability Details **File Location**: `emotion_memory.py`, lines 14 and 72–75; sensitive record construction occurs at lines 161–169 **Vulnerability Type**: Plaintext sensitive-data storage with insufficient access-control and retention safeguards **Risk Level**: Medium ### Vulnerable Code ```python STORAGE_FILE = os.path.expanduser("~/.memory/emotions/history.json") ``` ```python def save_history(history: List[Dict]): """保存历史情绪记录""" os.makedirs(os.path.dirname(STORAGE_FILE), exist_ok=True) with open(STORAGE_FILE, 'w', encoding='utf-8') as f: json.dump(history, f, ensure_ascii=False, indent=2) ``` ```python record = { "user_id": user_id, "timestamp": result["timestamp"], "emotion": result["emotion"], "score": result["score"], "keywords": result["keywords"], "context": message[:100], # 记录上下文 "last_care_time": last_care_time } ``` ### Technical Analysis Every invocation of `detect_emotion` stores a user identifier, inferred emotional state, matched keywords, and up to 100 characters of the user's message. The accumulated records are serialized as unencrypted JSON at a predictable path under the user's home directory. The implementation does not explicitly create the directory with mode `0700` or the file with mode `0600`; effective permissions therefore depend on the process environment and umask. It also provides no retention limit, deletion mechanism, encryption, or option to disable storage of raw conversation context. Because emotional profiles and conversation excerpts can constitute sensitive personal information, these omissions create an avoidable local disclosure risk. ### Attack Path 1. A user or integrating agent invokes `detect_emotion` with a message containing private information. 2. The function copies the first 100 characters of that message, along with the inferred emotion and user identifier, into a history record. 3. `save_history` writes the entire accumulated history to `~/.memor ...[truncated 1146 chars]
- Remediation
- ## Remediation Suggestions 1. **Minimize collected data** - Do not store raw message context by default. - Persist only fields strictly required for the feature, such as the emotion category and timestamp. - Make conversation-excerpt storage explicitly opt-in. 2. **Enforce restrictive permissions** - Create `~/.memory/emotions` with owner-only mode `0700`. - Create the history file with mode `0600`, rather than relying on the ambient umask. - Verify and correct permissions when loading existing storage. 3. **Protect data at rest** - Where confidentiality is required, encrypt records using credentials managed by an operating-system keychain or equivalent secure storage. - Do not hardcode encryption keys in the skill. 4. **Implement lifecycle controls** - Add a configurable retention period and automatic pruning. - Provide APIs to inspect, export, and permanently delete stored history. - Document what is collected, where it is stored, and how long it is retained. 5. **Harden file updates** - Write to an owner-only temporary file in the same protected directory. - Flush and atomically replace the destination to reduce corruption and unsafe partial updates. - Avoid following unexpected symbolic links where supported, and verify that the storage path is an expected regular file.
