T09 · Insecure Skill Coding Practices
- Location
SKILL.md:166- Finding
User-Controlled Path Traversal and Arbitrary File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 166-168
Vulnerability Type: Path traversal and unsafe file creation
Risk Level: Mediumpython filename = title.replace(" ", "_") + ".md" with open(filename, "w", encoding="utf-8") as f: f.write(note)Technical Analysis
The note title is incorporated directly into a filesystem path. Replacing spaces with underscores does not remove absolute paths, parent-directory components such as
../, platform-specific separators, or other path-control characters.Because
open()uses write mode, an existing destination file is truncated before the note is written. The implementation does not constrain the resolved path to a designated knowledge-vault directory, reject existing files, or protect against symbolic-link traversal.Attack Path
- An attacker supplies a crafted note title, such as
../../target. - The application transforms it into
../../target.md. open(..., "w")resolves the parent-directory components relative to the process working directory.- If the destination is writable, the target file is created or truncated and replaced with attacker-influenced Markdown content.
- If a predictable destination is a symbolic link, the write may affect the link target instead.
Impact Assessment
Exploitation permits creation or replacement of
.mdfiles accessible to the Agent process. The scope is limited by the operating-system privileges of that process and by the automatically appended.mdsuffix.Potential consequences include loss or corruption of project documentation, knowledge-base records, configuration stored in Markdown, or Agent instruction files. This does not independently provide privilege escalation, but overwriting a file subsequently interpreted by an Agent could influence later behavior.
- An attacker supplies a crafted note title, such as
- Remediation
View remediation
Remediation Suggestions
- Store notes exclusively beneath a dedicated vault directory.
- Convert titles into safe filenames using an allowlist such as letters, digits, hyphens, and underscores.
- Reject absolute paths,
..components, path separators, null bytes, and empty filenames. - Resolve both the vault and destination to canonical paths, then verify that the destination remains beneath the vault before writing.
- Use exclusive creation mode (
"x") or an explicit collision policy to prevent unintended overwrites. - Defend against symbolic-link attacks by rejecting symlink destinations and, where supported, using secure no-follow file-opening semantics.
- Generate an internal identifier for the filename and store the original user title only inside the note metadata.
Example hardening pattern:
python from pathlib import Path import re vault = Path("./vault").resolve() vault.mkdir(parents=True, exist_ok=True) safe_title = re.sub(r"[^A-Za-z0-9_-]+", "_", title).strip("_") if not safe_title: raise ValueError("Title does not produce a valid filename") destination = (vault / f"{safe_title}.md").resolve() if destination.parent != vault: raise ValueError("Destination is outside the knowledge vault") with destination.open("x", encoding="utf-8") as f: f.write(note)
