T09 · Insecure Skill Coding Practices
- Location
scripts/manage_courses.py:15- Finding
Path Traversal Allows File Creation Outside the Intended Storage Directory
- Content
View full analysis
Vulnerability Details
File Location:
scripts/manage_courses.py, lines 15-18
Vulnerability Type: Unrestricted path construction using a caller-controlled course name
Risk Level: Mediumpython filename = f"{name}_{timestamp}.md" filepath = os.path.join(STORAGE_DIR, filename) with open(filepath, 'w', encoding='utf-8') as f:Technical Analysis
The
nameparameter is incorporated directly into a filesystem path without validation or normalization. Although the intended destination is/home/ubuntu/yanxue_courses,os.path.join()does not guarantee that the resulting path remains beneath that directory.If
nameis absolute, the constructedfilenameis also absolute, causingos.path.join()to discardSTORAGE_DIR. A name containing traversal components such as../../can similarly resolve outside the storage directory. The script then writes caller-controlled course content to the resulting location with the permissions of the process running the Skill.The timestamp and
.mdsuffix limit the ability to overwrite a specifically named existing file, but they do not prevent creation of attacker-controlled files in other writable directories.Attack Path
- An attacker supplies a course name containing an absolute path or directory traversal components.
- The save operation is invoked through
manage_courses.py save <name> <content_path>. - The script appends a timestamp and
.mdextension but does not remove path separators or traversal sequences. os.path.join(STORAGE_DIR, filename)produces a path outside the intended storage directory.- The script creates a Markdown file containing attacker-controlled content in any existing directory writable by the running process.
Impact Assessment
Successful exploitation permits creation of timestamp-suffixed Markdown files outside
/home/ubuntu/yanxue_courses. The attacker gains the same filesystem write ...[truncated 364 chars]- Remediation
View remediation
Remediation Suggestions
- Reject absolute paths and course names containing
/,\,.., null bytes, or platform-specific path separators. - Convert the supplied course name to a safe filename using a strict allowlist of expected letters, digits, spaces, underscores, and hyphens.
- Resolve both the storage directory and destination path before writing, then verify that the destination remains beneath the storage directory.
- Use
pathlib.Pathfor explicit and portable path validation. - Consider exclusive file creation mode to avoid unintended replacement under concurrent execution.
- Return an error rather than silently rewriting an invalid name.
Example hardening pattern:
python import re from pathlib import Path STORAGE_DIR = Path("/home/ubuntu/yanxue_courses").resolve() def safe_destination(name, timestamp): safe_name = re.sub(r"[^A-Za-z0-9 _-]", "_", name).strip() if not safe_name: raise ValueError("Invalid course name") destination = (STORAGE_DIR / f"{safe_name}_{timestamp}.md").resolve() if not destination.is_relative_to(STORAGE_DIR): raise ValueError("Destination escapes the storage directory") return destination- Reject absolute paths and course names containing
