T09 · Insecure Skill Coding Practices
- Location
scripts/backup.py:221- Finding
File Symlinks Bypass the Documented Exclusion Policy
- Content
View full analysis
bool: """判断文件是否应被排除""" file_path = file_path.resolve() name = file_path.name name_lower = name.lower() ext = file_path.suffix.lower().lstrip(".") # 1. 符号链接/联接点 try: if file_path.is_symlink() or self._is_junction(file_path): self.stats["by_symlink"] += 1 self.stats["total_skipped"] += 1 return True ``` The file is subsequently added to the archive: ```python with tarfile.open(output_file, f"w:gz", compresslevel=compression) as tar: for file_path in files: try: arcname = normalize_tar_path(file_path) tar.add(file_path, arcname=arcname) ``` Archive names are also calculated from resolved paths: ```python def normalize_tar_path(path: Path) -> str: """将路径标准化为 tar 归档名,保留绝对路径""" abs_path = str(path.resolve()) if len(abs_path) >= 2 and abs_path[1] == ":": abs_path = abs_path[0] + "_/" + abs_path[2:] return abs_path.replace("\\", "/") ``` ### Technical Analysis `Path.resolve()` follows a symbolic link and returns its target before the code calls `is_symlink()`. The resolved target is ordinarily not itself a symlink, so the test no longer identifies the original directory entry as a symbolic link. The rebinding performed inside `is_excluded()` does not modify the `Path` object retained by `collect_files()`. As a result, the original file symlink can be appended to the collection and passed to `tar.add()`. Meanwhile, `normalize_tar_path()` derives the archive member name from the resolved target. This produces inconsistent behavior in which a link from the scanned workspace can be archived under a name representing its target. This violates the documente ...[truncated 1671 chars]- Remediation
View remediation
