T09 · Insecure Skill Coding Practices
Error
- Location
- skills/ui-ux-pro-max/scripts/design_system.py:504
- Finding
- Path Traversal Enables Filesystem Writes Outside the Design-System Directory<![CDATA[ ## Vulnerability Details **File Location**: `skills/ui-ux-pro-max/scripts/design_system.py`, lines 504–531 **Vulnerability Type**: Path traversal and unsafe file overwrite **Risk Level**: High ### Vulnerable Code ```python base_dir = Path(output_dir) if output_dir else Path.cwd() # Use project name for project-specific folder project_name = design_system.get("project_name", "default") project_slug = project_name.lower().replace(' ', '-') design_system_dir = base_dir / "design-system" / project_slug pages_dir = design_system_dir / "pages" created_files = [] # Create directories design_system_dir.mkdir(parents=True, exist_ok=True) pages_dir.mkdir(parents=True, exist_ok=True) master_file = design_system_dir / "MASTER.md" # Generate and write MASTER.md master_content = format_master_md(design_system) with open(master_file, 'w', encoding='utf-8') as f: f.write(master_content) created_files.append(str(master_file)) # If page is specified, create page override file with intelligent content if page: page_file = pages_dir / f"{page.lower().replace(' ', '-')}.md" page_content = format_page_override_md(design_system, page, page_query) with open(page_file, 'w', encoding='utf-8') as f: f.write(page_content) created_files.append(str(page_file)) ``` ### Technical Analysis The persistence function uses the CLI-controlled project name, page name, and output directory in filesystem paths without validating or canonicalizing them. Replacing spaces with hyphens is not sufficient sanitization. Values can still contain: - Parent-directory components such as `../` - Absolute path prefixes - Platform-specific path separators - Names that resolve through symbolic links `pathlib` also discards preceding path components when a later component is absolute. Consequently, an absolute `project_slug` or page-derived path can bypass the intended `base_dir/design-system/` location entirely. Both files are opened with mode `w`, so an existing t ...[truncated 1682 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict project and page names to a conservative allowlist, such as: ```python import re SAFE_SLUG = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$") def validate_slug(value: str) -> str: slug = value.strip().lower().replace(" ", "-") if not SAFE_SLUG.fullmatch(slug): raise ValueError("Invalid project or page name") return slug ``` 2. Reject absolute paths, `.` and `..` components, path separators, drive prefixes, and null characters. 3. Resolve the approved root and candidate destination, then enforce containment: ```python root = (base_dir / "design-system").resolve() target = (root / project_slug / "MASTER.md").resolve() if not target.is_relative_to(root): raise ValueError("Output path escapes the design-system directory") ``` 4. Apply the same containment check to page files. 5. Detect symbolic-link traversal where the threat model includes untrusted project directories. 6. Avoid silent overwrites. Use exclusive creation mode (`x`) or require explicit confirmation before replacing existing files. 7. Treat `--output-dir` as a privileged option and require explicit user authorization when it resolves outside the current project. 8. Add tests covering absolute paths, nested traversal, Windows drive paths, mixed separators, symbolic links, and overwrite attempts. ]]>
