T09 · Insecure Skill Coding Practices
- Location
scripts/generate.py:42- Finding
Arbitrary Local File Upload to an External Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate.py:42-74, invoked fromscripts/generate.py:197-208
Vulnerability Type: Unrestricted local file upload and sensitive information disclosure
Risk Level: HighVulnerable Code
python def upload_file(client: httpx.Client, api_key: str, file_path: str) -> str: """Upload a file to ComfyDeploy and return the URL.""" path = Path(file_path) print(f"[DEBUG] upload_file called for: {file_path}", flush=True) if not path.exists(): raise FileNotFoundError(f"File not found: {file_path}") # Determine content type suffix = path.suffix.lower() if suffix in [".jpg", ".jpeg"]: content_type = "image/jpeg" elif suffix == ".png": content_type = "image/png" elif suffix == ".webp": content_type = "image/webp" else: content_type = "application/octet-stream" print(f"[DEBUG] Content type: {content_type}", flush=True) # Upload file using multipart form print(f"[DEBUG] Opening file and preparing upload...", flush=True) with open(path, "rb") as f: files = {"file": (path.name, f, content_type)} print(f"[DEBUG] Sending POST to {API_BASE}/file/upload", flush=True) response = client.post( f"{API_BASE}/file/upload", headers={"Authorization": f"Bearer {api_key}"}, files=files )The upload is reached through the following argument handling:
python # Determine if image is URL or file image_url = args.image # Create HTTP client with httpx.Client(timeout=120.0) as client: # Upload image if it's a local file if not args.image.startswith(("http://", "https://")): print("Uploading image...") image_url = upload_file(client, api_key, args.image) else: print(f"Using image URL: {image_url}")T
...[truncated 2095 chars]
- Remediation
View remediation
Remediation Suggestions
- Permit only explicitly supported image formats such as JPEG, PNG, and WebP; reject all other extensions instead of using
application/octet-stream. - Decode the file with a maintained image library and reject files that cannot be parsed as the claimed image type.
- Validate the file's magic bytes rather than trusting its extension.
- Resolve the path with
Path.resolve()and require it to remain within an approved input directory or workspace. - Reject symbolic links where they are not required, or validate the final resolved target.
- Enforce a conservative maximum file size before opening or uploading the file.
- Clearly notify the user that the image will be transmitted to ComfyDeploy and require confirmation where the execution environment supports interactive approval.
- Avoid printing unnecessary local path information in logs.
- Permit only explicitly supported image formats such as JPEG, PNG, and WebP; reject all other extensions instead of using
