T09 · Insecure Skill Coding Practices
- Location
scripts/common/validators.py:57- Finding
Extension-Only File Validation Permits Unintended Local File Disclosure
- Content
View full analysis
Vulnerability Details
File Location:
scripts/common/validators.py:57-73; upload occurs atscripts/common/ocr_client.py:191-205
Vulnerability Type: Insufficient file-type validation and symbolic-link traversal
Risk Level: MediumVulnerable Code
python if not os.path.exists(file_path): return False, f"File not found: {file_path}" if not os.path.isfile(file_path): return False, f"Not a file: {file_path}" file_size = os.path.getsize(file_path) if file_size > MAX_FILE_SIZE: return False, f"File size exceeds {MAX_FILE_SIZE / 1024 / 1024}MB limit" ext = os.path.splitext(file_path)[1].lower() if ext not in ALLOWED_IMAGE_EXTENSIONS: return False, f"File extension '{ext}' not allowed" return True, NoneAfter validation, the complete file is read, Base64-encoded, and submitted to the remote service:
python file_path = os.path.expanduser(file_path.strip()) is_valid, error_msg = FileValidator.validate(file_path) if not is_valid: return OCRResult(code="FILE_ERROR", message=f"File validation failed: {error_msg}", data=None) try: with open(file_path, 'rb') as f: file_content = f.read() base64_content = base64.b64encode(file_content).decode('utf-8') except (IOError, OSError) as e: return OCRResult(code="FILE_READ_ERROR", message=f"Failed to read file: {str(e)}", data=None) param = self._build_request_param(base64_data=base64_content, input_configs=input_configs) response = self._send_request(param)Technical Analysis
The validator determines whether a local file is an image solely by examining its filename extension. It does not inspect image magic bytes, parse the file with an image decoder, or reject symbolic links.
os.path.isfile()follows symbolic links. Therefore, a path with an allowed image extension can be a symbolic link to another readable regular file. A non-image file can also simply be renamed with an ...[truncated 1696 chars]- Remediation
View remediation
Remediation Suggestions
- Resolve the submitted path with
Path.resolve(strict=True)and explicitly reject symbolic links usingPath.is_symlink()before opening the file. - Restrict local-file access to explicitly approved directories or to files selected through a trusted user-consent mechanism.
- Validate file contents rather than trusting the extension:
- Check recognized image magic bytes.
- Decode the file with a maintained image-processing library.
- Reject malformed, unsupported, or ambiguous content.
- Open and validate the same file descriptor that will be uploaded to reduce time-of-check/time-of-use race conditions.
- On supported platforms, use no-follow semantics such as
O_NOFOLLOWwhen opening user-controlled paths. - Preserve the existing size limit and enforce it again while reading to protect against files that change after validation.
- Resolve the submitted path with
