T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/ews-mail.py:299
- Finding
- Path Traversal and Arbitrary File Overwrite Through Attachment Filenames<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ews-mail.py`, lines 299-302 **Vulnerability Type**: Unsanitized file path construction **Risk Level**: High ### Vulnerable Code ```python if isinstance(att, FileAttachment) and att.content: path = os.path.join(dest_dir, att.name or f"attachment_{count}") with open(path, "wb") as f: f.write(att.content) ``` ### Technical Analysis The attachment name supplied by the Exchange server is used directly as a filesystem path component. The code does not reject absolute paths, parent-directory components such as `../`, or symbolic-link destinations. `os.path.join()` does not guarantee that the resulting path remains under `dest_dir`. If `att.name` is absolute, it can replace the preceding destination directory entirely. A relative name containing traversal components can similarly escape the intended directory. The file is opened in `wb` mode, which truncates an existing file before writing. Consequently, a malicious attachment filename can cause attacker-controlled attachment content to overwrite any file writable by the user running the Skill. ### Attack Path 1. An attacker sends a message containing a file attachment with a crafted filename, such as `../../.bashrc` or another traversal path accepted by the Exchange attachment interface. 2. The message appears in the target mailbox. 3. The user or Agent invokes `attachment-download` for that message. 4. The script concatenates the attacker-controlled filename with the selected destination directory without validation. 5. Path traversal causes the resolved location to escape the intended download directory. 6. The script opens the resolved path using `wb` and overwrites the target with attacker-controlled attachment content. 7. If the overwritten file is subsequently interpreted or executed, the attacker may obtain code execution with the privileges of the user running the Skill. ### Impact Assessment The direct impact is arbitrary ...[truncated 580 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Treat every attachment filename as untrusted input. 2. Remove directory components with `os.path.basename()` and reject empty, absolute, traversal, or special filenames. 3. Resolve both the destination directory and final path with `pathlib.Path.resolve()`, then verify that the final path remains beneath the destination directory. 4. Avoid silently overwriting existing files. Use exclusive creation mode such as `xb`, generate a unique filename, or require explicit user confirmation. 5. Consider symbolic-link attacks by opening files with platform-appropriate no-follow protections where available. 6. Apply restrictive file permissions when creating downloaded files. Example hardening pattern: ```python from pathlib import Path base = Path(dest_dir).expanduser().resolve() base.mkdir(parents=True, exist_ok=True) raw_name = att.name or f"attachment_{count}" safe_name = Path(raw_name).name if not safe_name or safe_name in {".", ".."}: raise ValueError("Invalid attachment filename") target = (base / safe_name).resolve() if target.parent != base: raise ValueError("Attachment path escapes destination directory") with target.open("xb") as f: f.write(att.content) ``` ]]>
