T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/parse_chat.py:172
- Finding
- Predictable Plaintext Output Enables Sensitive Data Disclosure and Symlink-Based File Overwrite## Vulnerability Details **File Location**: `scripts/parse_chat.py`, lines 172–175 **Vulnerability Type**: Predictable unsafe output file and plaintext retention **Risk Level**: Medium ### Vulnerable Code ```python # Save cleaned content to a temporary file temp_path = os.path.join(os.path.dirname(file_path), '_cleaned_temp.txt') with open(temp_path, 'w', encoding='utf-8') as f: f.write(cleaned) print(f"\nCleaned content saved to: {temp_path}") ``` ### Technical Analysis The parser unconditionally stores the complete cleaned conversation in a predictably named file, `_cleaned_temp.txt`, in the source file's directory. The file is not temporary despite its name: it is not automatically deleted, and no restrictive permissions are explicitly applied. Opening the path in `w` mode silently truncates an existing file and follows symbolic links. No validation checks whether the destination already exists, is a symbolic link, or points outside the intended directory. This creates two related risks: 1. **Plaintext disclosure and retention:** potentially sensitive personal or business conversations remain on disk after parsing. 2. **Symlink-based overwrite:** if an attacker can prepare the input directory, the predictable destination can be created as a symbolic link to another file writable by the parser's user. The parser will then truncate and replace that target with cleaned conversation content. The script's top-level output description states that it outputs parsed plaintext, but it does not disclose this persistent side effect. ### Attack Path 1. An attacker obtains write access to a directory from which a victim will parse a chat file, such as a shared extraction directory. 2. The attacker creates `_cleaned_temp.txt` as a symbolic link to another file writable by the victim. 3. The victim invokes `parse_chat.py` on a TXT or DOCX file in that directory. 4. The parser derives the fixed `_cleaned_temp.txt` destination and opens it in `w` mode. 5. The op ...[truncated 1204 chars]
- Remediation
- ## Remediation Suggestions 1. **Do not persist parsed conversations by default.** Return or print the cleaned data unless the user explicitly requests an output file. 2. **Require an explicit destination path** through a command-line option and clearly document that sensitive plaintext will be written. 3. **Prevent silent replacement** by opening new output files in exclusive creation mode (`x`) or requiring explicit overwrite confirmation. 4. **Reject symbolic links and non-regular files.** Validate the destination with `os.lstat()` and, where supported, open it using low-level flags such as `O_NOFOLLOW`, `O_CREAT`, and `O_EXCL`. 5. **Use restrictive permissions**, such as mode `0o600`, so only the owning user can access the output. 6. **Use secure temporary storage when persistence is transient.** Create files with Python's `tempfile` module in a trusted directory and delete them promptly. 7. **Avoid elevated execution.** Run the parser with only the minimum user permissions required. 8. **Add tests** covering pre-existing destinations, symbolic links, shared directories, permission handling, and cleanup behavior.
