T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/main.py:57
- Finding
- Arbitrary Local File Disclosure Through Insufficient Image Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py`, lines 57-87 and 160-176 **Vulnerability Type**: Arbitrary local file read and external data transmission **Risk Level**: High ### Vulnerable Code ```python def load_image_base64(value: str) -> str: if os.path.isfile(value): with open(value, "rb") as f: raw = f.read() try: raw_str = raw.decode("utf-8").strip() base64.b64decode(raw_str, validate=True) return raw_str except (UnicodeDecodeError, ValueError): pass if len(raw) > MAX_IMAGE_SIZE_BYTES: sys.exit(1) encoded = base64.b64encode(raw).decode("utf-8") return encoded ``` The resulting data is assigned to the Tencent Cloud request and transmitted externally: ```python if args.image_url: req.ImageUrl = args.image_url elif args.image_base64: req.ImageBase64 = load_image_base64(args.image_base64) else: sys.exit(1) try: resp = client.LicensePlateOCR(req) except TencentCloudSDKException as e: sys.exit(1) ``` ### Technical Analysis The `--image-base64` argument accepts either Base64 content or any path for which `os.path.isfile()` returns true. When a path is supplied, the script reads the entire file without first verifying that it is a supported PNG or JPEG image. If the file contains valid Base64 text, the decoded content is not checked for an image signature or decoded-size limit before being returned. Otherwise, any binary file of up to 10 MB is Base64-encoded and assigned to `req.ImageBase64`. The resulting content is transmitted to `ocr.tencentcloudapi.com` through the Tencent Cloud SDK. Base64 encoding is required for the declared OCR operation and is not inherently covert. The vulnerability arises because the implementation does not constrain encoding and transmission to legitimate image files. This behavior exceeds the minimum privileges required for license-plate OCR. The feature ...[truncated 1922 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate that local input is a regular, approved image before transmitting it: - Accept only PNG, JPG, and JPEG formats. - Verify file signatures rather than relying only on filename extensions. - Reject Base64 data whose decoded bytes do not have a supported image signature. 2. Enforce size limits before loading complete files: - Use `os.stat()` to reject oversized regular files before opening them. - Read using bounded or streaming operations. - Apply the limit to decoded Base64 data, including Base64 text loaded from a file. 3. Restrict file access: - Resolve paths with `pathlib.Path.resolve()`. - If the execution environment has an approved upload directory, require the resolved file to remain inside it. - Reject symbolic links where they are not explicitly required. - Reject device files, pipes, sockets, and other non-regular inputs. 4. Separate file and literal-Base64 inputs into distinct arguments so that a user or Agent cannot ambiguously convert a path into an upload. 5. Require explicit user confirmation before uploading local files, particularly when an Agent selected the path automatically. 6. Run the Skill under a dedicated, least-privileged account with access only to files required for the current OCR operation. ]]>
