T09 · Insecure Skill Coding Practices
- Location
scripts/stock_advisor.py:157- Finding
Arbitrary Filesystem Write Location Through Unsanitized Stock Code
- Content
View full analysis
Vulnerability Details
File Location:
scripts/stock_advisor.py, lines 157-162
Vulnerability Type: Improper path validation leading to writes outside the intended report directory
Risk Level: HighVulnerable Code
python ts_code_safe = ts_code.replace('.', '_') report_subdir = f"{ts_code_safe}_{timestamp}" report_dir = os.path.join(base_report_dir, report_subdir) if not os.path.exists(report_dir): os.makedirs(report_dir)Technical Analysis
The report directory is derived directly from the caller-controlled
ts_code. The only normalization performed is replacing periods with underscores. This does not reject absolute paths, path separators, drive prefixes, or other platform-specific path constructs.In particular, if
report_subdiris an absolute path,os.path.join(base_report_dir, report_subdir)discardsbase_report_dir. The application then creates the resulting directory and subsequently writes fixed-name Markdown and JSON report files into it.The vulnerability does not grant permissions beyond those already held by the Skill process, but it breaks the intended output-directory boundary. No canonical-path containment check is performed before filesystem operations.
Attack Path
- An attacker or untrusted caller invokes
StockAdvisorSystem.diagnose()with a crafted absolute-path-like stock code. - The value passes through
ts_code.replace('.', '_'), which does not remove path separators or reject absolute paths. os.path.join()resolves the attacker-controlled absolute component outsidebase_report_dir.os.makedirs()creates the attacker-selected directory if the process has permission.- The diagnostic workflow writes generated Markdown reports and, when
save_report()is called, a JSON report into that directory. - Existing fixed-name files at the destination may be overwritten by later report-writing operations.
Impact Assessment
Succes ...[truncated 716 chars]
- An attacker or untrusted caller invokes
- Remediation
View remediation
Remediation Suggestions
-
Enforce a strict stock-code allowlist before constructing any path. For example:
python import re if not re.fullmatch(r"[0-9]{6}\.(SH|SZ|BJ)", ts_code): raise ValueError("Invalid stock code") -
Generate the directory name only from validated components rather than attempting to sanitize arbitrary input.
-
Resolve both the report root and destination and verify containment:
python from pathlib import Path report_root = Path(base_report_dir).resolve() report_dir = (report_root / report_subdir).resolve() if report_root not in report_dir.parents: raise ValueError("Report path escapes the configured output directory") report_dir.mkdir(parents=True, exist_ok=False) -
Reject absolute paths, path separators, null bytes, drive prefixes, and reserved platform-specific names.
-
Run the Skill under a minimally privileged account with write access limited to a dedicated report directory.
-
Add tests covering absolute Unix paths, Windows drive paths, UNC paths, separators, malformed exchange suffixes, and unexpected Unicode path characters.
-
