T09 · Insecure Skill Coding Practices
Error
- Location
- generate_images.py:64
- Finding
- Shell Command Injection Through Unvalidated Credentials and API Response Values<![CDATA[ ## Vulnerability Details **File Location**: `generate_images.py:64-91` **Vulnerability Type**: OS command injection through `shell=True` and string interpolation **Risk Level**: High ### Vulnerable Code ```python def submit_task(prompt): cmd = f'''curl -s "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis" \\ -H "Content-Type: application/json" \\ -H "Authorization: Bearer {API_KEY}" \\ -H "X-DashScope-Async: enable" \\ -d '{{ "model": "wanx2.1-t2i-turbo", "input": {{ "prompt": "{prompt}" }}, "parameters": {{ "size": "720*1280", "n": 1 }} }}' ''' result = subprocess.run(cmd, shell=True, capture_output=True, text=True) return result.stdout def get_task_status(task_id): cmd = f'''curl -s "https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}" \\ -H "Authorization: Bearer {API_KEY}" ''' result = subprocess.run(cmd, shell=True, capture_output=True, text=True) return result.stdout def download_image(url, output_path): cmd = f'curl -s "{url}" -o "{output_path}"' subprocess.run(cmd, shell=True) ``` ### Technical Analysis The script constructs shell command strings by directly interpolating multiple values and then executes those strings with `subprocess.run(..., shell=True)`. The affected values include: - `API_KEY`, obtained from an environment variable or `~/.zshrc`. - `task_id`, obtained from the remote DashScope API response. - `url`, obtained from the remote DashScope API response. - `output_path`, currently derived from hard-coded paths but still passed through a shell. Shell quoting does not make these values safe. An interpolated value containing a double quote followed by shell metacharacters can terminate the intended quoted argument and inject an additional command. The same issue affects both the authorization header and values returned by the remote service. The JSON request is also assembled manually inside shell quoting. Alth ...[truncated 2083 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Eliminate `shell=True` entirely. 2. Prefer the official DashScope SDK or a Python HTTP client such as `urllib.request` or a properly pinned `requests` dependency. 3. If `curl` must be retained, pass an argument array without invoking a shell: ```python result = subprocess.run( [ "curl", "-sS", "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis", "-H", "Content-Type: application/json", "-H", f"Authorization: Bearer {API_KEY}", "-H", "X-DashScope-Async: enable", "--data-binary", json.dumps(payload), ], shell=False, capture_output=True, text=True, check=True, ) ``` 4. Build request bodies with `json.dumps()` rather than manual shell quoting. 5. Validate remote task IDs against the exact format documented by DashScope before using them. 6. Parse and validate download URLs with `urllib.parse`; require HTTPS and an expected host or documented host allowlist. 7. Use Python file operations such as `shutil.copy2()` instead of invoking `cp`. 8. Read credentials only from a dedicated secret provider or the process environment. Do not parse interactive shell startup files. 9. Add explicit timeouts, return-code checks, and safe error handling without printing credentials or full authorization headers. 10. Add regression tests containing quotes, semicolons, command substitutions, newlines, and other shell metacharacters to verify that values are always treated as data. ]]>
