VYPR
Moderate severityNVD Advisory· Published Nov 5, 2025· Updated Nov 6, 2025

Apache Doris-MCP-Server: Improper Access Control results in bypassing a "read-only" mode for doris-mcp-server MCP Server

CVE-2025-58337

Description

An attacker with a valid read-only account can bypass Doris MCP Server’s read-only mode due to improper access control, allowing modifications that should have been prevented by read-only restrictions.

Impact:

Bypasses read-only mode; attackers with read-only access may perform unauthorized modifications.

Recommended action for operators: Upgrade to version 0.6.0 as soon as possible (this release contains the fix).

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

An attacker with a valid read-only account can bypass read-only mode in Apache Doris MCP Server due to improper access control, enabling unauthorized modifications.

Vulnerability

Overview CVE-2025-58337 describes an improper access control vulnerability in Apache Doris MCP Server versions prior to 0.6.0. The server enforces a read-only mode for certain users, but due to missing security checks in the SQL execution path, read-only restrictions are not properly applied. This allows users with read-only credentials to execute write operations that should be blocked. [1][2]

Exploitation

Exploitation requires a valid read-only account on the Doris MCP Server. An attacker with such an account can craft requests that bypass the intended access controls, leveraging the SQL execution tools to perform unauthorized modifications. The vulnerability exists in the execute_sql_for_mcp function, which lacked proper security validation for read-only users. [3]

Impact

Successful exploitation enables an attacker to modify database records, change configurations, or perform other write operations despite having only read-only permissions. This compromises data integrity and can lead to unauthorized changes in the underlying Apache Doris database. [2][4]

Mitigation

The issue is fixed in Apache Doris MCP Server version 0.6.0, which introduces comprehensive security enhancements including token-based authentication, role-based permissions, and SQL security validation. Operators are strongly advised to upgrade immediately. [1][4]

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
doris-mcp-serverPyPI
< 0.6.00.6.0

Affected products

2

Patches

1
5923cc1c8973

[BUG]Fix security bug (#50)

https://github.com/apache/doris-mcp-serverYijia SuAug 29, 2025via ghsa
1 file changed · +69 14
  • doris_mcp_server/utils/query_executor.py+69 14 modified
    @@ -557,22 +557,67 @@ async def execute_sql_for_mcp(
                             "data": None
                         }
     
    +                # Import required security modules
    +                from .security import DorisSecurityManager, AuthContext, SecurityLevel
    +
    +                # Create proper auth context with read-only permissions
    +                auth_context = AuthContext(
    +                    user_id=user_id,
    +                    roles=["read_only_user"],  # Restrictive role for MCP interface
    +                    permissions=["read_data"],  # Only read permissions
    +                    session_id=session_id,
    +                    security_level=SecurityLevel.INTERNAL
    +                )
    +
    +                # Perform SQL security validation if enabled
    +                if hasattr(self.connection_manager, 'config') and hasattr(self.connection_manager.config, 'security'):
    +                    if self.connection_manager.config.security.enable_security_check:
    +                        try:
    +                            security_manager = DorisSecurityManager(self.connection_manager.config)
    +                            validation_result = await security_manager.validate_sql_security(sql, auth_context)
    +                            
    +                            if not validation_result.is_valid:
    +                                self.logger.warning(f"SQL security validation failed for query: {sql[:100]}...")
    +                                return {
    +                                    "success": False,
    +                                    "error": f"SQL security validation failed: {validation_result.error_message}",
    +                                    "error_type": "security_violation",
    +                                    "blocked_operations": validation_result.blocked_operations,
    +                                    "risk_level": validation_result.risk_level,
    +                                    "data": None,
    +                                    "metadata": {
    +                                        "query": sql,
    +                                        "validation_details": {
    +                                            "blocked_operations": validation_result.blocked_operations,
    +                                            "risk_level": validation_result.risk_level
    +                                        }
    +                                    }
    +                                }
    +                            else:
    +                                self.logger.debug(f"SQL security validation passed for query: {sql[:100]}...")
    +                        except Exception as security_error:
    +                            self.logger.error(f"Security validation error: {str(security_error)}")
    +                            # In case of security validation error, fail safe
    +                            return {
    +                                "success": False,
    +                                "error": f"Security validation system error: {str(security_error)}",
    +                                "error_type": "security_system_error",
    +                                "data": None,
    +                                "metadata": {
    +                                    "query": sql,
    +                                    "security_error": str(security_error)
    +                                }
    +                            }
    +                    else:
    +                        self.logger.info("SQL security check is disabled in configuration")
    +                else:
    +                    self.logger.warning("Security configuration not found, proceeding without validation")
    +
                     # Add LIMIT if not present and it's a SELECT query
                     if sql.upper().startswith("SELECT") and "LIMIT" not in sql.upper():
                         if sql.endswith(";"):
                             sql = sql[:-1]
                         sql = f"{sql} LIMIT {limit}"
    -
    -                # Create auth context for MCP calls
    -                class MockAuthContext:
    -                    def __init__(self):
    -                        self.user_id = user_id
    -                        self.roles = ["data_analyst"]
    -                        self.permissions = ["read_data", "execute_query"]
    -                        self.session_id = session_id
    -                        self.security_level = "internal"
    -
    -                auth_context = MockAuthContext()
                     
                     # Create query request
                     query_request = QueryRequest(
    @@ -827,9 +872,13 @@ def _analyze_query_distribution(
     
     # Unified convenience function for MCP integration
     async def execute_sql_query(sql: str, connection_manager: DorisConnectionManager, **kwargs) -> Dict[str, Any]:
    -    """Execute SQL query - unified convenience function for MCP tools"""
    +    """Execute SQL query - unified convenience function for MCP tools
    +    
    +    This function now includes security validation to ensure safe query execution.
    +    All queries are validated against the configured security policies before execution.
    +    """
         try:
    -        # Create query executor
    +        # Create query executor with the connection manager's configuration
             executor = DorisQueryExecutor(connection_manager)
             
             try:
    @@ -839,6 +888,7 @@ async def execute_sql_query(sql: str, connection_manager: DorisConnectionManager
                 session_id = kwargs.get("session_id", "mcp_session")
                 user_id = kwargs.get("user_id", "mcp_user")
                 
    +            # The execute_sql_for_mcp method now includes security validation
                 result = await executor.execute_sql_for_mcp(
                     sql=sql,
                     limit=limit,
    @@ -854,5 +904,10 @@ async def execute_sql_query(sql: str, connection_manager: DorisConnectionManager
             return {
                 "success": False,
                 "error": f"Query execution failed: {str(e)}",
    -            "data": None
    +            "error_type": "execution_error",
    +            "data": None,
    +            "metadata": {
    +                "query": sql,
    +                "execution_error": str(e)
    +            }
             }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.