GitHub Security Advisory: GHSA-4894-xqv6-vrfq
Package: mindsdb (PIP)
Severity: HIGH (CVSS 8.8)
CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable versions: < 25.9.1.1
Patched in: 25.9.1.1

Summary: MindsDB: Path Traversal in /api/files Leading to Remote Code Execution

Details:
### Summary

There is a path traversal vulnerability in Mindsdb's /api/files interface, which an authenticated attacker can exploit to achieve remote command execution.

### Details

The vulnerability exists in the "Upload File" module, which corresponds to the API endpoint /api/files. The affected code is located at mindsdb/api/http/namespaces/file.py:
```python
@ns_conf.route("/<name>")
@ns_conf.param("name", "MindsDB's name for file")
class File(Resource):
    @ns_conf.doc("put_file")
    @api_endpoint_metrics('PUT', '/files/file')
    def put(self, name: str):
        """add new file
        params in FormData:
            - file
            - original_file_name [optional]
        """

        data = {}
        mindsdb_file_name = name

        existing_file_names = ca.file_controller.get_files_names()

        def on_field(field):
            name = field.field_name.decode()
            value = field.value.decode()
            data[name] = value

        file_object = None

        def on_file(file):
            nonlocal file_object
            data["file"] = file.file_name.decode()
            file_object = file.file_object

        temp_dir_path = tempfile.mkdtemp(prefix="mindsdb_file_")

        if request.headers["Content-Type"].startswith("multipart/form-data"):
            parser = multipart.create_form_parser(
                headers=request.headers,
                on_field=on_field,
                on_file=on_file,
                config={
                    "UPLOAD_DIR": temp_dir_path.encode(),  # bytes required
                    "UPLOAD_KEEP_FILENAME": True,
                    "UPLOAD_KEEP_EXTENSIONS": True,
                    "MAX_MEMORY_FILE_SIZE": 0,
                },
            )

            while True:
                chunk = request.stream.read(8192)
                if not chunk:
                    break
                parser.write(chunk)
            parser.finalize()
            parser.close()

            if file_object is not None:
                if not file_object.closed:
                    try:
                        file_object.flush()
                    except (AttributeError, ValueError, OSError):
                        logger.debug("Failed to flush file_object before closing.", exc_info=True)
                    file_object.close()
                file_object = None
        else:
            data = request.json
```
Since the multipart file upload does not perform security checks on the uploaded file path, an attacker can perform path traversal by using ../ sequences in the filename field. The file write operation occurs before calling clear_filename and save_file, meaning there is no filtering of filenames or file types, allowing arbitrary content to be written to any path on the server.


### PoC

This vulnerability can be exploited to overwrite existing executable files, which retain their executable permissions after being overwritten. In addition to conventional file upload exploitation methods, w