T09 · Insecure Skill Coding Practices
- Location
scripts/save_file.py:31- Finding
Unrestricted File Creation and Destructive Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/save_file.py:31-35
Related Invocation Instructions:SKILL.md:45-58
Vulnerability Type: Arbitrary file write, path traversal, and unsafe overwrite
Risk Level: HighVulnerable Code
python # create dir if not exist os.makedirs(os.path.dirname(file_path), exist_ok=True) with open(file_path, "w", encoding="utf-8") as f: f.write(content)The path and content are accepted directly from command-line arguments at
scripts/save_file.py:40-54:python def main(): parser = argparse.ArgumentParser(description="Save content to a file") parser.add_argument("--path", type=str, required=True, help="Path to save the file") parser.add_argument( "--content", type=str, required=True, help="Content to write into the file", ) args = parser.parse_args() result = save_file(args.path, args.content)The Skill explicitly directs the Agent to invoke the script with a generated path at
SKILL.md:45-58:markdown ## 后续工作 在完成 Agent 代码编写后,调用脚本保存代码产物: - `agent_name/__init__.py`: 固定内容为 `from . import agent # noqa` - `agent_name/agent.py`:包含所有智能体的代码 其中,`agent_name` 是你认为合适的 Agent 的名称。 脚本调用方法为: ```bash python save_file.py --path ... --content ...text ### Technical Analysis The `--path` argument reaches `os.makedirs()` and `open()` without validation or confinement. The implementation does not: - Reject absolute paths. - Reject `..` path traversal. - Resolve and verify the target against a trusted output directory. - Restrict output to the two intended filenames. - Validate the generated Agent directory name. - prevent writes through symbolic links. - Detect existing files or require authorization before overwriting them. Python's `"w"` mode creates a missing file and truncates an existing file. Consequently, the script provides a general-purpose file-write primitive rather than a writer restricted to the generated Agent direct ...[truncated 1849 chars]- Remediation
View remediation
Remediation Suggestions
- Confine all output to a trusted root directory. Resolve both the trusted root and requested target, then reject any target that is not a descendant of the root.
python from pathlib import Path OUTPUT_ROOT = Path("/trusted/generated-agents").resolve() def resolve_output_path(relative_path: str) -> Path: supplied = Path(relative_path) if supplied.is_absolute(): raise ValueError("Absolute output paths are not allowed") target = (OUTPUT_ROOT / supplied).resolve() try: target.relative_to(OUTPUT_ROOT) except ValueError as exc: raise ValueError("Output path escapes the trusted root") from exc return target-
Validate the Agent name using an allowlist. Permit only a conservative identifier format, such as lowercase ASCII letters, digits, and underscores. Reject separators, dots, traversal tokens, and control characters.
-
Restrict allowed targets. Construct paths internally from the validated Agent name and permit only:
<agent_name>/__init__.py<agent_name>/agent.py
Do not accept a general-purpose path from the user or model.
-
Prevent unintended overwrites. Use exclusive creation mode (
"x") by default. If replacement is required, obtain explicit authorization and use an atomic write through a safely created temporary file followed byos.replace(). -
Defend against symbolic-link redirection. Reject symlink components and symlink targets. Where supported, use descriptor-based filesystem operations with no-follow semantics and revalidate the destination immediately before committing the file.
-
Apply least privilege. Execute the Skill under an account or sandbox that can write only to the dedicated generation directory.
-
Add negative security tests. Cover absolute paths,
../traversal, nested traversal, symlink targets, existing-file overwrite attempts, unexpected filenames, and malformed Agent names.
