T09 · Insecure Skill Coding Practices
- Location
scripts/search-jobs.py:149- Finding
Arbitrary File Overwrite Through User-Controlled Output Path
- Content
View full analysis
Vulnerability Details
File Location:
scripts/search-jobs.py, lines 149-150 and 160-188
Vulnerability Type: Arbitrary file overwrite
Risk Level: MediumTechnical Analysis
The
--outputcommand-line argument accepts an unrestricted filesystem path. That path is passed directly toopen()in write mode without validating that it is inside an approved output directory, checking whether it is a symbolic link, or preventing replacement of an existing file.Relevant code:
python def save_to_file(content, filepath): """保存结果到文件""" with open(filepath, 'w', encoding='utf-8') as f: f.write(content)python parser.add_argument('--output', type=str, default=None, help='输出文件路径')python if args.output: save_to_file(output, args.output) print(f"结果已保存到:{args.output}") else: print(output)Python's
open(filepath, 'w')truncates an existing regular file. It also follows symbolic links. Consequently, anyone able to influence the script arguments can overwrite any file writable by the account running the skill.This issue is particularly significant if an automation service invokes the script with elevated privileges or constructs
--outputfrom untrusted user input.Attack Path
- An attacker gains control over, or injects content into, the value supplied to
--output. - The attacker selects an existing file writable by the skill process, such as a workspace configuration file:
bash python scripts/search-jobs.py --output /path/to/writable/configuration save_to_file()opens that path usingwmode.- The original file is truncated and replaced with the generated report.
- Alternatively, where the attacker can create a symbolic link in an output location, the link can point to another process-writable target and
open()will follow it.
Exploitation does not permit writing arbitrary attacker-selected conte ...[truncated 897 chars]
- An attacker gains control over, or injects content into, the value supplied to
- Remediation
View remediation
Remediation Suggestions
- Restrict generated files to a dedicated project-controlled output directory.
- Resolve the requested path with
pathlib.Path.resolve()and verify that it remains beneath the approved directory. - Reject absolute paths and traversal components such as
..if arbitrary relative names are supported. - Refuse to overwrite existing files unless the caller supplies an explicit, trusted overwrite option.
- Defend against symbolic-link attacks by using operating-system flags such as
O_NOFOLLOW, where available. - Create files atomically with restrictive permissions, then rename them into place.
- Run the skill under a dedicated unprivileged account with access only to its own data directory.
Example validation pattern:
python from pathlib import Path OUTPUT_DIR = (Path(__file__).resolve().parents[1] / "output").resolve() def save_to_file(content, filename): OUTPUT_DIR.mkdir(mode=0o700, parents=True, exist_ok=True) target = (OUTPUT_DIR / filename).resolve() if OUTPUT_DIR not in target.parents: raise ValueError("Output path is outside the approved directory") if target.exists() or target.is_symlink(): raise FileExistsError("Refusing to overwrite an existing output") target.write_text(content, encoding="utf-8")
