T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/create_structure.py:61
- Finding
- Unsafe Overwrite and Symlink Following During Project Structure Creation## Vulnerability Details **File Location**: `scripts/create_structure.py`, lines 61-65 **Vulnerability Type**: Unsafe file overwrite and symlink traversal **Risk Level**: Medium ### Vulnerable Code ```python for file_path, content in example_files.items(): full_path = project_path / file_path full_path.parent.mkdir(parents=True, exist_ok=True) with open(full_path, 'w') as f: f.write(content) ``` The relevant generic confirmation logic is at lines 84-89: ```python if project_path.exists(): print(f"警告: 路径已存在: {project_path}") response = input("是否继续? (y/N): ") if response.lower() != 'y': print("已取消") sys.exit(0) ``` ### Technical Analysis The script opens every placeholder file with mode `w`, which truncates an existing file before writing the new content. It does not check whether individual files already exist or disclose which files will be replaced. For example, an existing `config/settings.json` is unconditionally replaced with `{}` after the user accepts only a generic project-level confirmation. The script also does not reject symbolic links or verify resolved-path containment. If a target file such as `config/settings.json`, or one of its parent directories, is a symbolic link, Python follows that link when opening the destination. A crafted project directory can therefore redirect a write outside the selected project root. This is a fixed-content arbitrary file-write primitive rather than arbitrary-content code execution: the attacker can choose a writable target through a symlink, while the content written is determined by the script's `example_files` mapping. ### Attack Path 1. An attacker prepares a directory that appears to be an existing project. 2. The attacker creates a symbolic link at a generated path, such as `config/settings.json`, pointing to a file writable by the victim. Alternatively, the directory already contains legitimate files at the placeholder paths. 3. The victim or an Agent ...[truncated 1305 chars]
- Remediation
- ## Remediation Suggestions 1. **Do not overwrite existing files by default.** Use exclusive creation mode and handle `FileExistsError`: ```python with open(full_path, "x", encoding="utf-8") as f: f.write(content) ``` Alternatively, explicitly skip every destination that already exists. 2. **Require granular overwrite consent.** If replacement is supported, enumerate the exact files that would be changed and require explicit confirmation before modifying them. 3. **Reject symbolic links.** Check every existing destination and parent path component with `is_symlink()` or `os.lstat()` and abort if a symbolic link is encountered. 4. **Enforce path containment.** Resolve the project root and each destination, then verify that every destination remains beneath the resolved root before writing: ```python root = project_path.resolve() destination = full_path.resolve(strict=False) destination.relative_to(root) ``` Abort when `relative_to` raises `ValueError`. 5. **Reduce race-condition exposure.** Path checks alone can be bypassed if an attacker can modify directories concurrently. On supported platforms, use directory-relative file operations with no-follow semantics, such as `openat`-style operations and `O_NOFOLLOW`. 6. **Use atomic replacement only when intentional.** Write to a safely and exclusively created temporary file within the verified destination directory, set appropriate permissions, and atomically rename it after explicit authorization. 7. **Add regression tests** covering existing files, symlinked target files, symlinked parent directories, paths outside the project root, and cancellation without filesystem changes.
