T05 · Unauthorized Access and Privilege Escalation
- Location
agent.py:9- Finding
Arbitrary Local File Read Through Unvalidated Image Path
- Content
View full analysis
Vulnerability Details
File Location:
agent.py, lines 9-20 and 40-54
Vulnerability Type: Arbitrary local file read caused by insufficient file-type and path validation
Risk Level: MediumVulnerable Code
python def file_to_base64(file_path): """将本地文件转换为 base64 字符串(含 data URL 头)""" with open(file_path, 'rb') as f: data = f.read() b64 = base64.b64encode(data).decode('utf-8') mime = mimetypes.guess_type(file_path)[0] or 'application/octet-stream' return f"data:{mime};base64,{b64}" def image_to_qr_data(image_path): """处理图片,返回要编码的数据""" base64_str = file_to_base64(image_path) if len(base64_str) <= MAX_QR_BYTES: return base64_str else: return f"图片太大无法直接存储,请上传至图床后使用 URL 生成二维码。"python def handle_call(args: dict): """技能入口函数""" content = args.get("content", "") image_path = args.get("image", "") # 优先处理图片 if image_path: if not os.path.exists(image_path): return {"error": f"图片文件不存在:{image_path}"} file_size = os.path.getsize(image_path) if file_size > 10 * 1024 * 1024: return {"error": "图片太大,请选择小于10MB的图片"} qr_data = image_to_qr_data(image_path) if qr_data.startswith("图片太大"): return {"message": qr_data}Technical Analysis
The
imageargument is treated as an arbitrary local filesystem path. The implementation only checks whether the path exists and whether its reported size is below 10 MB. It does not verify that the path points to an authorized file, that it is located within an approved directory, or that its contents are a valid image.mimetypes.guess_type()does not validate file contents; it merely infers a MIME type from the filename. Consequently, a caller can provide the path of any file readable by the skill process. The file is opened and read in full before the QR-capacity check is per ...[truncated 1437 chars]- Remediation
View remediation
Remediation Suggestions
- Restrict file access to explicitly approved directories or files rather than accepting unrestricted absolute paths.
- Resolve the canonical path with
os.path.realpath()orpathlib.Path.resolve()and verify that it remains within an authorized root directory. - Define and enforce a symlink policy. If symlinks are unnecessary, reject them with
os.path.islink()and use platform-safe file-opening controls where available. - Validate file contents as an image before encoding them. For example, open the file with Pillow, call
verify(), and only process supported formats. - Do not rely on filename extensions or
mimetypes.guess_type()for security validation. - Perform authorization and size checks before reading file contents, and stream bounded input where practical.
- Run the skill under a dedicated least-privilege account that cannot read credentials, private keys, or unrelated application data.
- Consider accepting image bytes or controlled upload handles instead of raw host filesystem paths.
