T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/convert_v2.py:267- Finding
Untrusted attachment paths can copy arbitrary local files into the Obsidian vault
- Content
View full analysis
int: """处理并复制附件""" copied_count = 0 for note in notes: for attachment in note.attachments: src_path = self.flomo_html_dir / attachment['src'] if not src_path.exists(): logger.warning(f"附件不存在: {src_path}") continue # 生成新的文件名 filename = src_path.name dest_path = self.attachments_dir / filename # 如果文件已存在,添加时间戳避免冲突 if dest_path.exists(): stem = dest_path.stem suffix = dest_path.suffix timestamp = note.datetime.strftime('%Y%m%d%H%M%S') dest_path = self.attachments_dir / f"{stem}_{timestamp}{suffix}" try: shutil.copy2(src_path, dest_path) attachment['obsidian_path'] = f"attachments/{dest_path.name}" copied_count += 1 ``` The attachment source value is extracted directly from imported HTML: ```python src = img.get('src', '') if src: attachments.append({ 'type': 'image', 'src': src, 'alt': img.get('alt', 'image') }) ``` ### Technical Analysis The converter treats an attachment `src` attribute from an imported HTML document as a trusted filesystem path. Joining an attacker-controlled path with `self.flomo_html_dir` does not guarantee containment. A relative value containing traversal components, such as `../../sensitive-file`, can resolve outside the export directory. A platform-supported absolute path may also override or bypass the intended base directory. The code checks only whether the resulting path exists; it does not canonicalize the path, reject abs ...[truncated 1483 chars]- Remediation
View remediation
