T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:60- Finding
Arbitrary File Creation Through Path Traversal
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py:60-73, with attacker-controlled input passed atscripts/main.py:1519-1524
Vulnerability Type: Path traversal and unrestricted file creation
Risk Level: HighVulnerable Code
python filepath = os.path.join(self.default_save_path, filename) # Select the WPS component based on document type app_map = { "writer": "wps", "spreadsheet": "et", "presentation": "wpp" } app = app_map.get(doc_type, "wps") # Create an empty file Path(filepath).touch()The
filenamevalue is supplied directly from command-line parameters:python if action == 'create': result = wps.create_document( doc_type=params.get('type', 'writer'), filename=params.get('filename', 'New Document.docx'), content=params.get('content', '') )Technical Analysis
The destination path is constructed by passing an unvalidated, attacker-influenced
filenametoos.path.join(). The code does not reject absolute paths, parent-directory components such as../, or symbolic-link traversal. It also does not resolve the resulting path and verify that it remains beneathdefault_save_path.An absolute second argument causes
os.path.join()to discard the intended base directory. A relative path containing enough parent-directory components can similarly escape the configured document directory.Path.touch()then creates the resolved file using the privileges of the process.The operation does not normally truncate an existing file, but it can create new empty files in arbitrary writable locations and update timestamps on existing files.
Attack Path
- An attacker supplies, or causes the Agent to generate, a document-creation request with a crafted filename such as
../../../../tmp/attacker-controlled. - The Agent invokes
scripts/main.py createand passes that value through thefilenameparamete ...[truncated 967 chars]
- An attacker supplies, or causes the Agent to generate, a document-creation request with a crafted filename such as
- Remediation
View remediation
Remediation Suggestions
- Reject absolute filenames and any path containing parent-directory traversal components.
- Resolve both the configured base directory and candidate destination before writing.
- Verify that the resolved destination is a child of the resolved base directory.
- Define an explicit filename policy, including permitted characters, length, and document extensions.
- Consider rejecting path separators entirely if the interface is intended to accept only filenames.
- Avoid following symbolic links when creating files where supported.
- Open new files with exclusive-creation semantics if overwriting or touching existing files is not intended.
Example hardening logic:
python base = Path(self.default_save_path).expanduser().resolve() supplied = Path(filename) if supplied.is_absolute() or ".." in supplied.parts: raise ValueError("Invalid filename") destination = (base / supplied).resolve() try: destination.relative_to(base) except ValueError: raise ValueError("Destination escapes the configured save directory") destination.parent.mkdir(parents=True, exist_ok=True) destination.touch(exist_ok=False)
