T09 · Insecure Skill Coding Practices
- Location
nex-timetrack.py:441- Finding
Arbitrary File Overwrite Through Export Path Traversal
- Content
View full analysis
Vulnerability Details
File Location:
nex-timetrack.py:441-445
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: Highpython output_file = args.output or f"timetrack_export.{args.format}" output_path = EXPORT_DIR / output_file with open(output_path, 'w', encoding='utf-8') as f: f.write(data)Technical Analysis
The value supplied through the
--outputargument is used directly as a path component without validation or containment checks. Python'spathlibpermits both traversal components and absolute paths:- A value such as
../../targetescapesEXPORT_DIR. - An absolute value causes the preceding
EXPORT_DIRcomponent to be discarded. - The use of
open(..., 'w')creates a missing file or truncates an existing file. - Symbolic links are followed, allowing a link inside the export directory to redirect the write elsewhere.
The exported contents are constrained to generated JSON or CSV, but fields within those formats include user-controlled time-entry data. The flaw therefore provides an attacker with an arbitrary file-write location, though not completely arbitrary file contents.
Attack Path
- The attacker obtains the ability to invoke the CLI or influences an agent to execute an export command.
- The attacker supplies an output path containing traversal components or an absolute path, for example:
bash nex-timetrack export json --output ../../target-file EXPORT_DIR / output_fileresolves outside the intended export directory.- The program opens the selected target with write-and-truncate behavior.
- Any existing user-writable target is overwritten with the generated export data.
A similar attack is possible by placing a symbolic link in the export directory and selecting that link as the output filename.
Impact Assessment
The attacker can create or overwrite files accessible to the account running ...[truncated 339 chars]
- A value such as
- Remediation
View remediation
Remediation Suggestions
- Restrict
--outputto a filename rather than an arbitrary path. - Reject absolute paths,
..components, directory separators, empty filenames, and platform-specific alternate separators. - Resolve the candidate path and verify that it remains under the resolved export directory:
python export_root = EXPORT_DIR.resolve() output_name = Path(args.output or f"timetrack_export.{args.format}") if output_name.is_absolute() or output_name.name != str(output_name): raise ValueError("Output must be a filename without directory components") output_path = (export_root / output_name).resolve() if output_path.parent != export_root: raise ValueError("Output path escapes the export directory") - Enforce the extension associated with the selected export format.
- Where overwriting is unnecessary, use exclusive creation mode (
'x') to prevent accidental truncation. - Defend against symbolic-link attacks by using operating-system facilities such as
O_NOFOLLOWwhere supported, or by securely creating files and verifying the resulting file descriptor. - Apply restrictive permissions to generated exports because they may contain client names, email addresses, billing rates, notes, and work descriptions.
- Restrict
