T09 · Insecure Skill Coding Practices
- Location
- scripts/generate.py:14
- Finding
- Arbitrary ComfyUI endpoint allows SSRF and disclosure of prompts and input images<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate.py:14, 45-59, 64-68, 181-205, 267, 282, 296` **Vulnerability Type**: Unrestricted server endpoint / server-side request forgery **Risk Level**: High ### Vulnerable Code ```python COMFYUI_URL = os.environ.get("COMFYUI_URL", "http://127.0.0.1:8188") ``` ```python def check_server(url=COMFYUI_URL): try: urllib.request.urlopen(f"{url}/system_stats", timeout=5) return True except Exception: return False def submit_prompt(workflow, url=COMFYUI_URL): data = json.dumps({"prompt": workflow}).encode("utf-8") req = urllib.request.Request(f"{url}/prompt", data=data, headers={"Content-Type": "application/json"}) resp = urllib.request.urlopen(req, timeout=30) return json.loads(resp.read()).get("prompt_id") ``` ```python def wait_for_completion(prompt_id, timeout=300, url=COMFYUI_URL): start = time.time() while time.time() - start < timeout: time.sleep(2) try: resp = urllib.request.urlopen(f"{url}/history/{prompt_id}", timeout=10) ``` ```python def upload_image(image_path, url=COMFYUI_URL): """Upload an image to ComfyUI input directory via API.""" if not os.path.exists(image_path): raise FileNotFoundError(f"Image not found: {image_path}") filename = os.path.basename(image_path) with open(image_path, "rb") as f: boundary = "----ComfyUIFormBoundary" body = ( f"--{boundary}\r\n" f'Content-Disposition: form-data; name="image"; filename="{filename}"\r\n' f"Content-Type: image/png\r\n\r\n" ).encode() + f.read() + f"\r\n--{boundary}--\r\n".encode() req = urllib.request.Request( f"{url}/upload/image", data=body, headers={"Content-Type": f"multipart/form-data; boundary={boundary}"}) try: urllib.request.urlopen(req, timeout=10) except Exception: pass return file ...[truncated 2319 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `--url` for normal Skill operation and force the endpoint to `http://127.0.0.1:8188`. 2. If endpoint configurability is required, parse it with `urllib.parse.urlsplit()` and enforce an explicit allowlist: - Permit only `http` or `https`. - Permit only loopback addresses by default. - Reject embedded credentials, fragments, unexpected paths, and unsupported ports. - Resolve hostnames and verify that every resolved address belongs to the intended range. 3. Require an explicit opt-in flag for remote endpoints and display a warning before prompts or images are transmitted. 4. Require HTTPS and authenticated API access for any approved remote endpoint. 5. Apply outbound network controls so the Skill cannot access metadata endpoints, private subnets, or unrelated local services. 6. Document that I2V uploads the complete selected image to the configured server. ]]>
