T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/generate_image.py:85
- Finding
- Arbitrary Local File Disclosure Through Unvalidated Python Image Input<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_image.py:85-90`, `scripts/generate_image.py:153-163`, and `scripts/generate_image.py:206` **Vulnerability Type**: Arbitrary local file read and third-party disclosure **Risk Level**: Medium ### Vulnerable Code ```python def encode_image_to_base64(image_path): """将图片文件转换为base64编码""" try: with open(image_path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") except Exception as e: print(f"错误: 无法读取图片文件 {image_path} - {e}") sys.exit(1) ``` ```python for image_path in input_images: if not os.path.exists(image_path): print(f"错误: 输入图片不存在: {image_path}") sys.exit(1) image_base64 = encode_image_to_base64(image_path) parts.append({"inlineData": {"mimeType": "image/png", "data": image_base64}}) ``` ```python response = requests.post(url, headers=headers, json=payload, timeout=400) ``` ### Technical Analysis The `--input-image` argument accepts an arbitrary filesystem path. The implementation checks only whether that path exists before opening it in binary mode and reading its complete contents. It does not: - Verify that the path is inside an approved user workspace. - Reject symbolic links, device files, or other special files. - Verify image signatures or decode the file as an image. - Enforce a maximum input size. - Derive the MIME type from validated content. All input is labeled as `image/png`, regardless of its actual format. Consequently, any readable non-image file can be Base64-encoded and inserted into the outbound JSON request. Base64 is expected as a transport encoding for legitimate image editing and is not itself evidence of malicious obfuscation. Likewise, sending valid user-selected images to the declared image-generation service is necessary for image editing. The vulnerability arises because the script does not constrain this capability to actual, authorized image files. ### Attack Pat ...[truncated 1362 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Restrict accessible paths** - Resolve every path with `Path.resolve(strict=True)`. - Require the resolved path to be inside an explicitly configured workspace or upload directory. - Reject paths that escape the approved directory. 2. **Reject unsafe filesystem objects** - Refuse symbolic links. - Require `Path.is_file()` rather than checking only existence. - Reject device files, sockets, named pipes, and directories. - Consider opening files with platform-supported no-follow semantics to reduce time-of-check/time-of-use risks. 3. **Validate actual image content** - Decode the input with a trusted image library. - Permit only explicitly supported formats. - Verify the magic bytes and decoded image structure instead of relying on an extension. - Set the outbound MIME type from the validated format rather than always using `image/png`. 4. **Enforce resource limits** - Apply conservative maximum file-size and image-dimension limits before encoding. - Read only regular files and fail closed on malformed input. 5. **Require informed authorization** - Display the canonical path and remote destination before upload. - Require explicit confirmation for each local file, particularly when invocation is Agent-generated. - Clearly document that prompts and images are transmitted to a third-party proxy. 6. **Apply runtime least privilege** - Run the Skill under an account or sandbox that can read only the approved workspace. - Do not expose home directories, credential stores, SSH directories, or unrelated project files to the process. ]]>
