T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/upload_asset.py:57
- Finding
- Arbitrary Readable Local Files Can Be Uploaded to the Remote Vidau API<![CDATA[ ## Vulnerability Details **File Location**: `scripts/upload_asset.py`, lines 57–68 and 87–121 **Vulnerability Type**: Missing file-type, file-size, and path-scope validation **Risk Level**: High ### Vulnerable Code ```python def _build_multipart_body(file_path: str, field_name: str) -> Tuple[bytes, str]: """Build multipart/form-data body. Returns (body_bytes, boundary).""" boundary = uuid.uuid4().hex filename = os.path.basename(file_path) with open(file_path, "rb") as f: file_data = f.read() content_type = mimetypes.guess_type(file_path)[0] or "application/octet-stream" part = ( f'--{boundary}\r\n' f'Content-Disposition: form-data; name="{field_name}"; filename="{filename}"\r\n' f'Content-Type: {content_type}\r\n\r\n' ).encode("utf-8") + file_data + f'\r\n--{boundary}--\r\n'.encode("utf-8") return part, boundary ``` ```python path = os.path.expanduser(args.file) if not os.path.isfile(path): print(f"Error: not a file: {path}", file=sys.stderr) sys.exit(1) file_hash = _file_sha256(path) cache = _load_cache() cached = cache.get(file_hash) if cached and cached.get("url") and cached.get("assetId"): out = { "code": "200", "message": "success", "data": {"url": cached["url"], "assetId": cached["assetId"]}, } print(json.dumps(out, ensure_ascii=False)) return api_key = api_client.get_api_key() if not api_key: print( "Error: VIDAU_API_KEY is not set. Register at https://www.superaiglobal.com/ " "and set apiKey or env.VIDAU_API_KEY in OpenClaw skills.entries.vidau.", file=sys.stderr, ) sys.exit(1) body, boundary = _build_multipart_body(path, args.field) headers = { "Authorization": f"Bearer {api_key}", "Content-Type": f"multipart/form-data; boundary={boundary}", "Content-Length": str(len(body)), } try: req = Request(UPLOAD_URL, data=body, headers=headers, method="POST") with urlopen(req, time ...[truncated 2414 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict accepted formats to an explicit allowlist of required image and video types. 2. Validate file signatures with trusted media parsers instead of relying only on extensions or `mimetypes.guess_type()`. 3. Reject `application/octet-stream` unless explicitly required and approved. 4. Resolve the path with `os.path.realpath()` and require it to reside within an approved workspace or user-selected directory. 5. Require explicit confirmation that displays the resolved local path and the remote destination before upload. 6. Enforce configurable file-size limits before hashing or reading the content. 7. Stream the multipart upload in bounded chunks rather than loading the complete file into memory. 8. Document that uploaded files leave the local environment and may be retained by the remote provider. ]]>
