T09 · Insecure Skill Coding Practices
- Location
- scripts/tensorslab_image.py:169
- Finding
- API-Controlled Task Identifier Allows Output Path Traversal<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tensorslab_image.py`, lines 169-173 and 278-280 **Vulnerability Type**: Path traversal through an untrusted filename component **Risk Level**: High ### Vulnerable Code ```python if result.get("code") == 1000: task_id = result.get("data", {}).get("taskid") logger.info(f"✅ Task created successfully! Task ID: {task_id}") return task_id ``` ```python for i, url in enumerate(urls): filename = f"{task_id}_{i}" output_path = output_dir / filename ``` The derived path is subsequently passed to `download_image()`, where the response is written to disk: ```python final_path = output_path.with_suffix(ext) with open(final_path, 'wb') as f: f.write(response.content) ``` ### Technical Analysis The task identifier is obtained directly from the remote API response and used as part of a local filesystem path without validation or normalization. Python's `pathlib` permits traversal components such as `../` in joined paths. An absolute path component can also supersede the preceding output directory. Consequently, a malicious or compromised API could return a task identifier containing traversal or absolute-path syntax. The resulting destination could escape the configured output directory. The application opens the destination in `wb` mode, which creates a new file or truncates an existing file. The `_0` index and remotely influenced extension constrain the exact resulting filename, but they do not guarantee that it remains inside the intended directory. ### Attack Path 1. A user invokes the image-generation client. 2. The client authenticates to the remote API and submits a generation request. 3. A compromised or malicious API response returns a task ID containing traversal components or an absolute path. 4. The client accepts the task ID without validation. 5. The client polls until the API reports that the task is complete. 6. It constructs `output_dir / f"{task_id}_{i}"`. 7. Th ...[truncated 696 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Validate task IDs using a strict allowlist, such as `^[A-Za-z0-9_-]{1,128}$`. - Do not use remotely supplied identifiers directly as local filenames. Generate a local UUID or random filename and retain the task ID only as metadata. - Resolve both the output directory and destination, then verify containment before writing: ```python base = output_dir.resolve() destination = (base / safe_filename).resolve() if destination.parent != base: raise TensorsLabAPIError("Unsafe output path") ``` - If nested output directories are intentionally supported, use `destination.is_relative_to(base)` on supported Python versions. - Open newly created files with exclusive creation where overwriting is unnecessary. - Add tests covering `../`, absolute paths, Windows drive paths, path separators, empty IDs, and excessively long IDs. ]]>
