T09 · Insecure Skill Coding Practices
- Location
scripts/generate_word_report.py:189- Finding
Unsanitized Station Name Permits Report Path Traversal
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_word_report.py:189-194; related unsafe filename construction also occurs inscripts/generate_report.py:87-88,scripts/generate_report.py:128-129, andscripts/generate_report.py:176-177
Vulnerability Type: Path traversal and arbitrary file creation
Risk Level: HighVulnerable Code
python # Generate a filename from the user-controlled station name filename = f"{station_name}_{date_str}_巡检日报.docx" output_file = OUTPUT_DIR / filename # Save the document OUTPUT_DIR.mkdir(parents=True, exist_ok=True) doc.save(str(output_file))Related Markdown report generation:
python output_file = OUTPUT_DIR / f"daily_{station_name}_{date_str}.md" output_file.write_text(content, encoding='utf-8')python output_file = OUTPUT_DIR / f"weekly_{station_name}_{week_str}.md" output_file.write_text(content, encoding='utf-8')python output_file = OUTPUT_DIR / f"monthly_{station_name}_{month_str}.md" output_file.write_text(content, encoding='utf-8')Technical Analysis
The
station_namevalue originates from the required--stationcommand-line argument and is incorporated directly into an output path. The application does not reject absolute paths, path separators, parent-directory components, control characters, or platform-specific path syntax.In
generate_word_report.py, the station name appears at the beginning of the filename. A value containing components such as../../is therefore resolved relative toOUTPUT_DIRand can escape the intended Word-report directory.The Markdown generators prepend strings such as
daily_to the station name, making exploitation dependent on the constructed intermediate path layout, but they still fail to enforce that the resolved destination remains belowOUTPUT_DIR.The fixed output extensions constrain the names that can be targeted, but they do not prevent una ...[truncated 1267 chars]
- Remediation
View remediation
Remediation Suggestions
-
Treat station names as display data, not filesystem paths.
-
Convert the station name to a strict filename-safe identifier using an allowlist such as letters, digits, spaces, hyphens, and underscores.
-
Explicitly reject
/,\,.., absolute paths, drive prefixes, null bytes, and control characters. -
Resolve the final path and verify that it remains under the resolved output directory before writing:
python import re from pathlib import Path def safe_filename_component(value: str) -> str: value = value.strip() if not re.fullmatch(r"[\w -]{1,100}", value, flags=re.UNICODE): raise ValueError("Station name contains invalid filename characters") return value.replace(" ", "_") output_root = OUTPUT_DIR.resolve() safe_station = safe_filename_component(station_name) output_file = ( output_root / f"{safe_station}_{date_str}_inspection-report.docx" ).resolve() if output_root not in output_file.parents: raise ValueError("Output path escapes the report directory") -
Apply the same validation and containment check to daily, weekly, and monthly Markdown output.
-
If replacement is not required, use exclusive file creation or generate a unique identifier to prevent accidental overwrites.
-
Add tests covering absolute paths, nested paths, repeated parent components, backslash traversal, Unicode separator-like characters, and excessively long names.
-
