T09 · Insecure Skill Coding Practices
- Location
scripts/generate_notes.py:28- Finding
Arbitrary File Creation Through Unvalidated Path Components
- Content
View full analysis
:"/\\|?*]', '', author)[:30].strip() safe_title = re.sub(r'[<>:"/\\|?*]', '', title)[:50].strip() if not safe_author: safe_author = '未知作者' if not safe_title: safe_title = '未知书名' # 构建路径 folder = os.path.join(output_dir, category, country, safe_author) note_file = os.path.join(folder, f"{safe_title}.md") if os.path.exists(note_file): skipped += 1 continue # Markdown内容 content = f"""# {title} - **作者**: {author} - **分类**: {category} - **国家**: {country} - **格式**: {book.get('format', '未知')} - **文件**: {book.get('filename', '')} ## 内容简介 {book.get('introduction', '暂无简介')} --- *来源: {book.get('intro_source', '网络')}* """ try: os.makedirs(folder, exist_ok=True) with open(note_file, 'w', encoding='utf-8') as f: ``` ### Technical Analysis The `category` and `country` values are loaded from a caller-supplied JSON index and used directly as filesystem path components. Unlike `author` and `title`, these fields receive no sanitization or structural validation. An attacker can provide values containing parent-directory components such as `..`, or absolute paths. `os.path.join()` does not enforce containment beneath `output_dir`: traversal components are resolved by the filesystem, while an absolute component can cause preceding components—including `output_dir`—to be discarded. The subsequent calls to `os.makedirs()` and `open()` there ...[truncated 1970 chars]- Remediation
View remediation
:"/\\|?*]', '', str(value)).strip() if value in {'', '.', '..'}: return fallback return value[:maximum_length] safe_country = safe_component(country, 'Unknown', 30) safe_author = safe_component(author, 'Unknown Author', 30) safe_title = safe_component(title, 'Unknown Title', 50) root = Path(output_dir).resolve() folder = (root / category / safe_country / safe_author).resolve() note_file = (folder / f"{safe_title}.md").resolve() if root != note_file and root not in note_file.parents: raise ValueError("Generated path escapes the output directory") folder.mkdir(parents=True, exist_ok=True) with note_file.open('x', encoding='utf-8') as output: output.write(content) ``` The allowlist must use the a ...[truncated 176 chars]
