T09 · Insecure Skill Coding Practices
- Location
scripts/hook_generator.py:187- Finding
Output Path Traversal Through an Unsanitized Topic
- Content
View full analysis
Vulnerability Details
File Location:
scripts/hook_generator.py:187-198
Vulnerability Type: Path traversal and unauthorized file write
Risk Level: Mediumpython def save_to_file(hooks, topic, output_dir): """保存到文件""" import os import json from pathlib import Path date_str = datetime.now().strftime("%Y-%m-%d") out_path = Path(output_dir) / f"hooks_{topic[:10]}_{date_str}.json" out_path.parent.mkdir(parents=True, exist_ok=True) with open(out_path, "w", encoding="utf-8") as f: json.dump({"topic": topic, "hooks": hooks, "generated_at": date_str}, f, ensure_ascii=False, indent=2) return out_pathTechnical Analysis
The
topicvalue originates from the user-controlled--topiccommand-line argument. Its first ten characters are inserted directly into the output path without removing path separators, rejecting..components, or verifying the resolved destination.Although the generated path begins with the fixed
hooks_prefix, a slash in the topic can turn that prefix into a directory name. Subsequent traversal components can then escape the intended output directory. For example, a topic beginning withx/../../tmpproduces a path structurally equivalent to:text <output_dir>/hooks_x/../../tmp_YYYY-MM-DD.jsonAfter filesystem path resolution, this can target a location outside
output_dir. The call tomkdir(parents=True, exist_ok=True)creates the attacker-influenced parent path, whileopen(..., "w")creates or truncates the resulting file.Exploitation is constrained by the ten-character topic slice, the fixed filename prefix and date suffix, filesystem layout, and the permissions of the process. Nevertheless, the intended output-directory security boundary is not enforced.
Attack Path
- An attacker or untrusted caller invokes the script with
--outputenabled. - The attacker supplies a
--topicvalue ...[truncated 1151 chars]
- An attacker or untrusted caller invokes the script with
- Remediation
View remediation
Remediation Suggestions
- Do not use raw user input as a path component. Generate filenames from an opaque identifier, such as a UUID or a cryptographic hash of the topic.
- If a readable topic-derived filename is required, apply a strict allowlist and replace every character outside a limited set such as ASCII letters, digits, underscores, and hyphens.
- Resolve both the output directory and candidate path before writing, then verify that the candidate remains inside the output directory.
- Reject empty or invalid sanitized filenames rather than silently accepting dangerous input.
- Consider exclusive file creation with mode
"x"if overwriting existing files is not required.
Example hardening approach:
python import hashlib from pathlib import Path output_root = Path(output_dir).resolve() output_root.mkdir(parents=True, exist_ok=True) topic_id = hashlib.sha256(topic.encode("utf-8")).hexdigest()[:16] out_path = (output_root / f"hooks_{topic_id}_{date_str}.json").resolve() if not out_path.is_relative_to(output_root): raise ValueError("Resolved output path is outside the output directory") with out_path.open("x", encoding="utf-8") as f: json.dump( {"topic": topic, "hooks": hooks, "generated_at": date_str}, f, ensure_ascii=False, indent=2, )Add regression tests using topics containing
/,\,.., absolute-path syntax, Unicode separator-like characters, and symlinked output directories. Each test should verify that no file is created outside the resolved output root.
