T05 · Unauthorized Access and Privilege Escalation
- Location
comfyui.py:243- Finding
Unrestricted Local File Upload to a User-Configurable Remote Server
- Content
View full analysis
Vulnerability Details
File Location:
comfyui.py:243-255, with command exposure atcomfyui.py:700-710andcomfyui.py:738-755
Vulnerability Type: Arbitrary local file read and remote upload
Risk Level: MediumVulnerable Code
python async def upload_file(self, file_path: str, subfolder: str = "", filename: str = None) -> Dict[str, Any]: """Upload an image file to the server""" try: session = await self._get_session() with open(file_path, 'rb') as f: data = aiohttp.FormData() data.add_field('image', f, filename=filename or os.path.basename(file_path)) data.add_field('subfolder', subfolder) data.add_field('type', 'input') async with session.post(f"{self.server_url}/upload/image", data=data) as resp: return await resp.json() except Exception as e: return {"error": str(e)}The unrestricted method is exposed through a command handler:
python async def handle_upload(args: List[str]) -> Dict[str, Any]: comfy = await get_comfyui() if not comfy.server_url: return {"error": "Please configure the server address first"} if not args: return {"error": "Usage: upload <file_path> [subfolder] [filename]"} file_path = args[0] subfolder = args[1] if len(args) > 1 else "" filename = args[2] if len(args) > 2 else None return await comfy.upload_file(file_path, subfolder, filename)It is registered in the public command dispatcher:
python handlers = { "set_url": handle_set_url, "status": handle_status, "generate": handle_generate, "sys_stats": handle_system_stats, "queue": handle_queue_status, "history": handle_history, "submit": handle_submit_task, "cancel": handle_cancel_task, "interrupt": handle_interrupt, "models": ...[truncated 2516 chars]- Remediation
View remediation
Remediation Suggestions
- Remove the
uploadcommand if local-file uploads are not essential to the intended text-to-image feature. - If uploads are required, restrict source files to a dedicated, explicitly configured upload directory.
- Resolve the requested path with
pathlib.Path.resolve()and verify that it remains beneath the allowed directory before opening it. Reject traversal, symbolic-link escapes, absolute paths outside the boundary, and special device files. - Validate uploads as expected image formats using file signatures or a trusted image parser rather than relying only on extensions.
- Enforce conservative file-size limits and permit only regular files.
- Require explicit user confirmation that displays the canonical source path and destination hostname before transmission.
- Restrict destinations to HTTPS servers on an explicit trusted-host allowlist. Reject arbitrary loopback, link-local, private-network, and untrusted external destinations where they are not required.
- Separate file-upload permission from ordinary generation permission so callers allowed to generate images do not automatically receive filesystem-read capability.
- Document the upload feature, destination behavior, and required filesystem and network permissions in
SKILL.md. - Avoid returning raw exception messages to untrusted callers because they may disclose local paths or network details; log detailed errors securely and return a generic failure response.
- Remove the
