T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/screenshot.py:18
- Finding
- Unrestricted Recursive Deletion Through Configurable Screenshot Directory## Vulnerability Details **File Location**: `scripts/screenshot.py`, lines 18 and 48–62 **Vulnerability Type**: Arbitrary directory content deletion through an unvalidated environment-controlled path **Risk Level**: High ```python SCREENSHOT_DIR = os.environ.get("SCREENSHOT_DIR", r"D:\CopyFromScreen") ``` ```python def prepare_screenshot_dir(): """准备截图目录:存在则清空,不存在则创建。""" target = Path(SCREENSHOT_DIR) if target.exists(): if target.is_dir(): for item in target.iterdir(): if item.is_file(): item.unlink() elif item.is_dir(): shutil.rmtree(item) else: target.unlink() target.mkdir(parents=True) else: target.mkdir(parents=True) ``` ### Technical Analysis The `SCREENSHOT_DIR` value is read directly from the process environment and used as the deletion target without validating its resolved location, ownership, type, or relationship to an approved screenshot directory. If the selected path is an existing directory, the script deletes every immediate file and recursively removes every immediate subdirectory. It does not verify that the directory was created by this skill, reject filesystem roots or sensitive locations, require a dedicated marker file, or limit deletion to generated PNG files. The code also performs separate path checks followed by destructive operations, leaving potential filesystem race conditions. Symbolic links, junctions, or other reparse-point behavior may further undermine assumptions about where deletion occurs, depending on the Windows filesystem configuration and Python runtime behavior. ### Attack Path 1. An attacker, wrapper process, compromised launcher, or user-controlled execution environment sets `SCREENSHOT_DIR` to an existing writable directory containing valuable data. 2. The skill is invoked with `python scripts/screenshot.p ...[truncated 1044 chars]
- Remediation
- ## Remediation Suggestions 1. Do not recursively clear an arbitrary environment-supplied directory. Create a unique, dedicated output directory for each execution instead. 2. Resolve the configured path with `Path.resolve()` and require it to be a descendant of a fixed, application-owned base directory. 3. Explicitly reject filesystem roots, drive roots, home directories, known system directories, and paths that equal the approved base directory itself. 4. Reject symbolic links, junctions, and other reparse points before performing destructive operations. 5. Place a private marker file in directories created by the skill and refuse cleanup unless the marker is present and valid. 6. Delete only files matching the skill's expected filename pattern and extension rather than deleting all directory contents. 7. Use restrictive directory permissions and run the script without administrative privileges. 8. Handle path validation and deletion defensively to reduce time-of-check/time-of-use race conditions. 9. Prefer retention limits or collision-resistant filenames over clearing previous output.
