CVE-2023-49796 (Python, published 2023-12-11T21:15Z)
Description: value: MindsDB connects artificial intelligence models to real time data. Versions prior to 23.11.4.1 contain a limited file write vulnerability in `file.py` Users should use MindsDB's `staging` branch or v23.11.4.1, which contain a fix for the issue.
Severity: nan (CVSS v3 base score: 5.3)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/mindsdb/mindsdb
Files changed:
mindsdb/api/http/namespaces/file.py
mindsdb/integrations/handlers/llama_index_handler/llama_index_handler.py
mindsdb/integrations/handlers/web_handler/web_handler.py
mindsdb/utilities/security.py
Commit message: fixes:
- SSRF
- arbitrary file write
https://github.com/mindsdb/mindsdb_private/issues/341


Vulnerable code:
            data["file"] = file.file_name.decode()
            data["file"] = data["name"]
        original_file_name = data.get("original_file_name")
            reader = SimpleWebPageReader(html_to_text=True).load_data([args['using']['source_url_link']])
                        f'url can be url = "someurl", you can also crawl multiple sites, as follows: url IN ("url1", "url2", ..)')
            

Fixed code:
from mindsdb.utilities.security import is_private_url, clear_filename
            data["file"] = clear_filename(file.file_name.decode())
            data["file"] = clear_filename(data["name"])
            if is_cloud and is_private_url(url):
                return http_error(
                    400, f'URL is private: {url}'
                )

        original_file_name = clear_filename(data.get("original_file_name"))
from mindsdb.utilities.security import is_private_url
            url = args['using']['source_url_link']
            config = Config()
            is_cloud = config.get("cloud", False)
            if is_cloud and is_private_url(url):
                raise Exception(f'URL is private: {url}')

            reader = SimpleWebPageReader(html_to_text=True).load_data([url])
from mindsdb.utilities.security import is_private_url
from mindsdb.utilities.config import Config
                        f'url can be url = "someurl", you can also crawl multiple sites, as follows:'
                        f' url IN ("url1", "url2", ..)'
                    )

        config = Config()
        is_cloud = config.get("cloud", False)
        if is_cloud:
            urls = [
                url
                for url in urls
                if not is_private_url(url)
            ]

from urllib.parse import urlparse
import socket
import ipaddress


def is_private_url(url: str):
    """
    Raises exception if url is private

    :param url: url to check
    """

    hostname = urlparse(url).hostname
    if not hostname:
        # Unable find hostname in url
        return True
    ip = socket.gethostbyname(hostname)
    return ipaddress.ip_address(ip).is_private


def clear_filename(filename: str):
    """
    Removes path symbols from filename which could be used for path injection
    :param s:
    :return:
    """

    if not filename:
        return filename
    badchars = '\\/:*?\"<>|'
    for c in badchars:
        filename = filename.replace(c, '')
    return filename