T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:59- Finding
Unrestricted Output Path Allows Arbitrary File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py, lines 59 and 78-79
Vulnerability Type: User-controlled path traversal and arbitrary file overwrite
Risk Level: MediumVulnerable Code
python parser.add_argument("--output", "-o", default="sop.txt", help="Output file")python with open(args.output, 'w') as f: f.write(sop)Technical Analysis
The command-line
--outputargument is passed directly toopen()in write mode without path validation or confinement to an approved workspace. The application accepts absolute paths and relative traversal sequences such as../.Because mode
'w'creates a file when it does not exist and truncates an existing file before writing, an attacker who can control the invocation arguments can create or overwrite any file writable by the process. This behavior also conflicts with the controls identified inSKILL.md, which call for rejecting../traversal and restricting output to the workspace.The issue does not independently elevate operating-system privileges. Its reach is limited to files accessible under the account and sandbox permissions used to run the Skill.
Attack Path
-
An attacker gains control over, or influences, the command-line arguments supplied to the Skill.
-
The attacker provides an absolute path or traversal path, for example:
bash python3 scripts/main.py \ --name "Test" \ --scope "Test scope" \ --responsibility "Operator" \ --output "../../target-file" -
The script passes
../../target-filedirectly toopen(args.output, 'w'). -
The operating system resolves the path outside the intended working directory.
-
If the process has write permission, the target is created or its existing contents are truncated and replaced with the generated SOP.
Impact Assessment
Successful exploitation permits file creation or destructive overwrite with the privileges of the process running the Skill. Potential con ...[truncated 513 chars]
-
- Remediation
View remediation
Remediation Suggestions
- Define a fixed, trusted output directory controlled by the application.
- Resolve the requested path with
pathlib.Path.resolve()and verify that the resulting path remains under the trusted directory. - Reject absolute paths,
..traversal, and paths resolving through symlinks outside the permitted directory. - If subdirectories are unnecessary, accept only a filename and reject directory separators.
- Prevent unintended replacement by opening files in exclusive creation mode (
'x') or requiring explicit overwrite confirmation. - Run the Skill with least-privilege filesystem permissions and sandbox-level write restrictions.
- Specify an encoding explicitly, such as
encoding="utf-8". - Add tests covering absolute paths, traversal paths, symlink escapes, and attempts to overwrite existing files.
A possible hardened approach is:
python from pathlib import Path OUTPUT_DIR = (Path.cwd() / "output").resolve() OUTPUT_DIR.mkdir(parents=True, exist_ok=True) requested_name = Path(args.output) if requested_name.is_absolute(): raise ValueError("Absolute output paths are not allowed") output_path = (OUTPUT_DIR / requested_name).resolve() if OUTPUT_DIR not in output_path.parents: raise ValueError("Output path must remain inside the output directory") with output_path.open("x", encoding="utf-8") as f: f.write(sop)
