T09 · Insecure Skill Coding Practices
Warning
- Location
- generate_video.py:36
- Finding
- Unrestricted Local File Disclosure Through the Image Input## Vulnerability Details **File Location**: `generate_video.py`, lines 36–81 and 151–166 **Vulnerability Type**: Arbitrary local file read and transmission to an external service **Risk Level**: Medium ### Vulnerable Code ```python # Convert local image to data URI def image_to_data_uri(image_path: str) -> str: """Convert local image to data URI.""" if not os.path.exists(image_path): raise FileNotFoundError(f"Image file not found: {image_path}") print(f"Converting image to data URI: {image_path}", file=sys.stderr) # Detect mime type ext = Path(image_path).suffix.lower() mime_types = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif', '.webp': 'image/webp' } mime_type = mime_types.get(ext, 'image/jpeg') with open(image_path, "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8") data_uri = f"data:{mime_type};base64,{image_data}" print(f"Image converted to data URI ({len(data_uri)} chars)", file=sys.stderr) return data_uri ``` ```python def create_video_task( prompt: str, model: str = "sora2-portrait-4s", image_url: Optional[str] = None ) -> dict: """Create a video generation task.""" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } payload = { "model": model, "prompt": prompt } if image_url: payload["image_url"] = image_url response = requests.post( f"{API_BASE}/v1/video/generations", headers=headers, json=payload ) response.raise_for_status() return response.json() ``` ```python # Handle image parameter - upload if local file image_url = None if args.image: if args.image.startswith(("http:// ...[truncated 3297 chars]
- Remediation
- ## Remediation Suggestions 1. **Restrict accessible paths** - Resolve the input with `Path.resolve()`. - Require local images to reside under an explicitly configured upload directory. - Verify containment using `Path.is_relative_to()` or an equivalent safe check after canonicalization. - Reject absolute paths when they are not explicitly required. 2. **Reject unsafe filesystem objects** - Require the input to be a regular file. - Reject symlinks, device files, named pipes, sockets, and directories. - Where race conditions matter, open files using platform controls that prevent symlink following and validate the opened file descriptor. 3. **Validate actual image content** - Use a maintained image decoder to parse and verify the file. - Do not rely on the filename extension or caller-provided MIME type. - Permit only the image formats required by the API. - Consider decoding and re-encoding the image to remove unrelated embedded content. 4. **Apply resource limits** - Enforce a conservative maximum file size before reading. - Enforce maximum decoded dimensions and pixel counts to prevent decompression-bomb behavior. - Avoid reading unbounded files into memory. 5. **Require informed authorization** - Clearly state that local image content will be transmitted to XLXAI. - In interactive contexts, request confirmation before uploading a local file. - In automated contexts, require an explicit opt-in flag or allowlisted input directory. 6. **Minimize external exposure** - Confirm the provider's retention, logging, and privacy policies. - Avoid logging image contents or data URIs. - Ensure errors cannot echo the request body or authorization header.
