T09 · Insecure Skill Coding Practices
Error
- Location
- seedance.py:212
- Finding
- Shell Command Injection Through an API-Controlled Task Identifier## Vulnerability Details **File Location**: `seedance.py`, lines 212-230 **Vulnerability Type**: Shell command injection **Risk Level**: High **Affected Platform**: macOS, when video downloading is enabled ### Vulnerable Code ```python filename = f"seedance_{task_id}_{int(time.time())}.mp4" filepath = download_path / filename print(f"\nDownloading video to {filepath}...") try: urllib.request.urlretrieve(video_url, str(filepath)) print(f"Saved to: {filepath}") # Open on macOS if sys.platform == "darwin": os.system(f'open "{filepath}"') except Exception as e: print(f"Download failed: {e}", file=sys.stderr) ``` ### Technical Analysis The `task_id` value is incorporated into a local filename without validation. For newly created tasks, this value originates from the remote Ark API response. It can also enter the same code path through the positional task identifier accepted by the `wait` command. The resulting `filepath` is interpolated into a command string passed to `os.system()`. Although the path is enclosed in double quotes, embedded double quotes and shell metacharacters are not escaped. Because `os.system()` invokes a command shell, a malicious task identifier can terminate the quoted argument and append an additional shell command. Exploitation requires the polling request for the crafted task identifier to produce a successful task response with a downloadable video URL. This could occur if the trusted remote API were compromised, returned attacker-controlled task metadata, or an attacker could otherwise control a compatible API response. The vulnerable shell call is macOS-specific and is reached only after the video download succeeds. ### Attack Path 1. The attacker causes the application to process a task identifier containing a quote and shell metacharacters. 2. The corresponding task-status request returns a successful result and a valid downloadable `video_url`. ...[truncated 1270 chars]
- Remediation
- ## Remediation Suggestions 1. Eliminate shell interpretation by replacing `os.system()` with an argument-vector subprocess call: ```python import subprocess if sys.platform == "darwin": subprocess.run( ["open", str(filepath)], check=False, shell=False, ) ``` 2. Validate task identifiers before using them in filenames. Apply a strict allowlist matching the documented identifier format, for example: ```python import re if not re.fullmatch(r"[A-Za-z0-9_-]{1,128}", task_id): raise ValueError("Invalid task identifier") ``` 3. Decouple remote identifiers from filesystem names. Prefer a locally generated UUID as the filename and retain the remote task identifier only as metadata. 4. Resolve the final destination and verify that it remains within the requested download directory before writing: ```python download_root = Path(download_dir).expanduser().resolve() filepath = (download_root / safe_filename).resolve() if download_root not in filepath.parents: raise ValueError("Download path escapes the destination directory") ``` 5. Restrict downloaded video URLs to expected schemes and, where supported by the API contract, trusted hosts. Reject local-file schemes and unexpected redirects. 6. Add regression tests using task identifiers containing quotes, semicolons, command substitutions, control characters, and path separators. Verify that these inputs are rejected and never reach a shell.
