T09 · Insecure Skill Coding Practices
- Location
generate_video.py:36- Finding
Unrestricted Local File Disclosure Through the Image Input
- Content
View full analysis
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: MediumVulnerable 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_uripython 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
View remediation
Remediation Suggestions
-
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.
- Resolve the input with
-
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.
-
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.
-
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.
-
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.
-
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.
-
