{
"event": "PreToolUse",
"tool_name": "mcp__mcp-docs__docs_update",
"tool_input": {
"id": 43,
"content": "<nav class=\"breadcrumb\">\n <a href=\"\/docs\">Dokumentation<\/a> » <a href=\"\/docs\/mcp\/mcp-db\">MCP-DB<\/a> » Validators\n<\/nav>\n\n<h1>MCP-DB Validators<\/h1>\n<p>SQL-Validierung nach dem Single Responsibility Principle.<\/p>\n\n<h2>QueryValidator<\/h2>\n<p>Validiert SELECT-Queries für das <code>db_select<\/code> Tool.<\/p>\n\n<pre><code>\"\"\"SRP: Separate Validierungslogik\"\"\"\nfrom typing import Tuple\nimport re\nfrom config import Config\n\nclass QueryValidator:\n \"\"\"Validiert SQL Queries - SRP: Nur Validierung\"\"\"\n\n @staticmethod\n def validate_query(query: str, database: str, max_rows: int) -> Tuple[bool, str]:\n \"\"\"\n Validiert eine Query gegen alle Sicherheitsregeln.\n\n Returns:\n (is_valid, error_message)\n \"\"\"\n # Basis-Validierung\n if not query or len(query) < 1:\n return False, \"Query must not be empty\"\n\n if len(query) > Config.MAX_QUERY_LENGTH:\n return False, f\"Query must be max {Config.MAX_QUERY_LENGTH} chars\"\n\n # Nur SELECT erlaubt\n query_upper = query.strip().upper()\n if not query_upper.startswith(\"SELECT\"):\n return False, \"Only SELECT queries allowed\"\n\n # Dangerous Keyword Blocklist\n for keyword in Config.BLOCKED_KEYWORDS:\n pattern = r'\\b' + re.escape(keyword) + r'\\b'\n if re.search(pattern, query_upper):\n return False, f\"Blocked keyword detected: {keyword}\"\n\n # Database Allowlist\n if database not in Config.ALLOWED_DATABASES:\n return False, f\"Database '{database}' not allowed\"\n\n # Max Rows prüfen\n if max_rows < 1 or max_rows > Config.MAX_ROWS:\n return False, f\"max_rows must be 1-{Config.MAX_ROWS}\"\n\n # Table Allowlist\n from_tables = QueryValidator._extract_table_names(query_upper)\n for table in from_tables:\n if \"INFORMATION_SCHEMA\" in table:\n continue\n table_clean = table.split('.')[-1]\n if table_clean not in [t.upper() for t in Config.ALLOWED_TABLES]:\n return False, f\"Table '{table}' not allowed\"\n\n return True, \"\"<\/code><\/pre>\n\n<h3>Validierungsschritte (QueryValidator)<\/h3>\n<table>\n <tr><th>#<\/th><th>Prüfung<\/th><th>Fehler bei<\/th><\/tr>\n <tr><td>1<\/td><td>Query nicht leer<\/td><td>Leere Query<\/td><\/tr>\n <tr><td>2<\/td><td>Query-Länge<\/td><td>> 2000 Zeichen<\/td><\/tr>\n <tr><td>3<\/td><td>SELECT-Only<\/td><td>Nicht mit SELECT beginnend<\/td><\/tr>\n <tr><td>4<\/td><td>Keyword-Blocklist<\/td><td>Blockiertes Keyword gefunden<\/td><\/tr>\n <tr><td>5<\/td><td>Database-Allowlist<\/td><td>Datenbank nicht erlaubt<\/td><\/tr>\n <tr><td>6<\/td><td>Max-Rows<\/td><td>< 1 oder > 100<\/td><\/tr>\n <tr><td>7<\/td><td>Table-Allowlist<\/td><td>Tabelle nicht erlaubt<\/td><\/tr>\n<\/table>\n\n<h2>ExecuteValidator<\/h2>\n<p>Validiert DDL-Statements für das <code>db_execute<\/code> Tool.<\/p>\n\n<pre><code>\"\"\"Execute Validator - Validierung für DDL\/DML Statements.\"\"\"\nimport re\nfrom config import Config\n\nclass ExecuteValidator:\n \"\"\"Validiert DDL\/DML Statements gegen Sicherheitsregeln.\"\"\"\n\n # Erlaubte Statement-Typen\n ALLOWED_STATEMENTS: list[str] = [\"ALTER\", \"CREATE\", \"DROP\", \"TRUNCATE\", \"SET\"]\n\n # Erlaubte SET-Variablen (Whitelist)\n ALLOWED_SET_VARS: list[str] = [\"FOREIGN_KEY_CHECKS\"]\n\n # Verbotene Patterns (kritisch!)\n FORBIDDEN_PATTERNS: list[str] = [\n r\"\\bDROP\\s+DATABASE\\b\",\n r\"\\bDROP\\s+SCHEMA\\b\",\n r\"\\bCREATE\\s+DATABASE\\b\",\n r\"\\bCREATE\\s+SCHEMA\\b\",\n r\"\\bGRANT\\b\",\n r\"\\bREVOKE\\b\",\n r\"\\bSHUTDOWN\\b\",\n ]\n\n # Verbotene Datenbanken (System-DBs)\n FORBIDDEN_DATABASES: list[str] = [\n \"information_schema\",\n \"mysql\",\n \"performance_schema\",\n \"sys\",\n ]\n\n @classmethod\n def validate_statement(cls, statement: str, database: str) -> tuple[bool, str]:\n \"\"\"\n Validiert ein DDL\/DML Statement.\n\n Returns:\n Tuple (is_valid, error_message)\n \"\"\"\n if not statement or len(statement.strip()) < 5:\n return False, \"Statement must not be empty\"\n\n if len(statement) > Config.MAX_QUERY_LENGTH:\n return False, f\"Statement exceeds max length\"\n\n statement_upper = statement.strip().upper()\n\n # Prüfe ob Statement mit erlaubtem Keyword beginnt\n statement_type = cls._get_statement_type(statement_upper)\n if statement_type is None:\n return False, f\"Statement type not allowed. Allowed: {', '.join(cls.ALLOWED_STATEMENTS)}\"\n\n # Bei SET: nur erlaubte Variablen\n if statement_type == \"SET\":\n allowed = any(var in statement_upper for var in cls.ALLOWED_SET_VARS)\n if not allowed:\n return False, f\"SET variable not allowed. Allowed: {', '.join(cls.ALLOWED_SET_VARS)}\"\n\n # Prüfe verbotene Patterns\n for pattern in cls.FORBIDDEN_PATTERNS:\n if re.search(pattern, statement_upper):\n return False, f\"Forbidden pattern detected\"\n\n # Prüfe Datenbank\n if database not in Config.ALLOWED_DATABASES:\n return False, f\"Database '{database}' not allowed\"\n\n # Prüfe ob Statement gegen System-DB zielt\n for forbidden_db in cls.FORBIDDEN_DATABASES:\n if re.search(rf\"\\b{forbidden_db}\\b\", statement_upper, re.IGNORECASE):\n return False, f\"Operations on '{forbidden_db}' are forbidden\"\n\n return True, \"\"<\/code><\/pre>\n\n<h3>Validierungsschritte (ExecuteValidator)<\/h3>\n<table>\n <tr><th>#<\/th><th>Prüfung<\/th><th>Fehler bei<\/th><\/tr>\n <tr><td>1<\/td><td>Statement nicht leer<\/td><td>Leeres Statement<\/td><\/tr>\n <tr><td>2<\/td><td>Statement-Länge<\/td><td>> 2000 Zeichen<\/td><\/tr>\n <tr><td>3<\/td><td>Statement-Typ<\/td><td>Nicht ALTER\/CREATE\/DROP\/TRUNCATE\/SET<\/td><\/tr>\n <tr><td>4<\/td><td>SET-Variablen<\/td><td>Nicht in ALLOWED_SET_VARS<\/td><\/tr>\n <tr><td>5<\/td><td>Forbidden Patterns<\/td><td>DROP DATABASE, GRANT, etc.<\/td><\/tr>\n <tr><td>6<\/td><td>Database-Allowlist<\/td><td>Datenbank nicht erlaubt<\/td><\/tr>\n <tr><td>7<\/td><td>System-DB-Schutz<\/td><td>mysql, information_schema, etc.<\/td><\/tr>\n<\/table>\n\n<h3>Erlaubte DDL-Statements<\/h3>\n<table>\n <tr><th>Typ<\/th><th>Beispiel<\/th><th>Status<\/th><\/tr>\n <tr><td>ALTER TABLE<\/td><td><code>ALTER TABLE tasks ADD COLUMN priority INT<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>CREATE TABLE<\/td><td><code>CREATE TABLE temp_data (...)<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>CREATE INDEX<\/td><td><code>CREATE INDEX idx_name ON table(col)<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>DROP TABLE<\/td><td><code>DROP TABLE temp_data<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>DROP INDEX<\/td><td><code>DROP INDEX idx_name ON table<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>TRUNCATE<\/td><td><code>TRUNCATE TABLE temp_data<\/code><\/td><td>Erlaubt<\/td><\/tr>\n <tr><td>SET<\/td><td><code>SET FOREIGN_KEY_CHECKS = 0<\/code><\/td><td>Erlaubt<\/td><\/tr>\n<\/table>\n\n<h3>Verbotene Patterns<\/h3>\n<table>\n <tr><th>Pattern<\/th><th>Beschreibung<\/th><\/tr>\n <tr><td>DROP DATABASE<\/td><td>Datenbank-Löschung verboten<\/td><\/tr>\n <tr><td>DROP SCHEMA<\/td><td>Schema-Löschung verboten<\/td><\/tr>\n <tr><td>CREATE DATABASE<\/td><td>Datenbank-Erstellung verboten<\/td><\/tr>\n <tr><td>CREATE SCHEMA<\/td><td>Schema-Erstellung verboten<\/td><\/tr>\n <tr><td>GRANT<\/td><td>Rechte-Vergabe verboten<\/td><\/tr>\n <tr><td>REVOKE<\/td><td>Rechte-Entzug verboten<\/td><\/tr>\n <tr><td>SHUTDOWN<\/td><td>Server-Shutdown verboten<\/td><\/tr>\n<\/table>\n\n<h2>Keyword-Erkennung<\/h2>\n<p>Keywords werden mit Word Boundaries erkannt:<\/p>\n<pre><code># Regex-Pattern für Keyword \"DROP\"\npattern = r'\\bDROP\\b'\n\n# Blockiert:\n\"SELECT * FROM t; DROP TABLE t\" # DROP erkannt\n\n# Nicht blockiert (kein vollständiges Wort):\n\"SELECT dropdown FROM t\" # DROP nicht erkannt<\/code><\/pre>\n\n<h2>Testfälle<\/h2>\n<pre><code># QueryValidator - Muss DENIED returnen:\n\"SELECT * FROM mcp_log; DROP TABLE mcp_log\" # DROP\n\"SELECT LOAD_FILE('\/etc\/passwd')\" # LOAD_FILE\n\"SELECT * FROM users\" # users nicht erlaubt\n\"SELECT SLEEP(10)\" # SLEEP\n\n# ExecuteValidator - Muss DENIED returnen:\n\"DROP DATABASE ki_dev\" # Forbidden Pattern\n\"GRANT ALL ON ki_dev.* TO user\" # GRANT verboten\n\"ALTER TABLE mysql.user ADD COLUMN x INT\" # System-DB\n\n# ExecuteValidator - Muss SUCCESS returnen:\n\"ALTER TABLE tasks ADD COLUMN priority INT\" # Erlaubt\n\"CREATE INDEX idx_status ON tasks(status)\" # Erlaubt\n\"SET FOREIGN_KEY_CHECKS = 0\" # Erlaubte Variable<\/code><\/pre>\n\n<h2>Verwandte Kapitel<\/h2>\n<ul>\n <li><a href=\"\/docs\/mcp\/mcp-db-config\">Konfiguration<\/a> - Allowlists und Blocklists<\/li>\n <li><a href=\"\/docs\/mcp\/mcp-db-security\">Sicherheit<\/a> - Gesamtkonzept<\/li>\n <li><a href=\"\/docs\/mcp\/mcp-db-tools\">Tools<\/a> - db_select und db_execute<\/li>\n<\/ul>"
}
}
{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 43,\n \"parent_id\": 36,\n \"slug\": \"mcp-db-validators\",\n \"path\": \"\/mcp\/mcp-db\/mcp-db-validators\",\n \"title\": \"Validators\",\n \"description\": \"SQL-Validierung nach dem Single Responsibility Principle.\",\n \"content\": \"<nav class=\\\"breadcrumb\\\">\\n <a href=\\\"\/docs\\\">Dokumentation<\/a> » <a href=\\\"\/docs\/mcp\/mcp-db\\\">MCP-DB<\/a> » Validators\\n<\/nav>\\n\\n<h1>MCP-DB Validators<\/h1>\\n<p>SQL-Validierung nach dem Single Responsibility Principle.<\/p>\\n\\n<h2>QueryValidator<\/h2>\\n<p>Validiert SELECT-Queries für das <code>db_select<\/code> Tool.<\/p>\\n\\n<pre><code>\\\"\\\"\\\"SRP: Separate Validierungslogik\\\"\\\"\\\"\\nfrom typing import Tuple\\nimport re\\nfrom config import Config\\n\\nclass QueryValidator:\\n \\\"\\\"\\\"Validiert SQL Queries - SRP: Nur Validierung\\\"\\\"\\\"\\n\\n @staticmethod\\n def validate_query(query: str, database: str, max_rows: int) -> Tuple[bool, str]:\\n \\\"\\\"\\\"\\n Validiert eine Query gegen alle Sicherheitsregeln.\\n\\n Returns:\\n (is_valid, error_message)\\n \\\"\\\"\\\"\\n # Basis-Validierung\\n if not query or len(query) < 1:\\n return False, \\\"Query must not be empty\\\"\\n\\n if len(query) > Config.MAX_QUERY_LENGTH:\\n return False, f\\\"Query must be max {Config.MAX_QUERY_LENGTH} chars\\\"\\n\\n # Nur SELECT erlaubt\\n query_upper = query.strip().upper()\\n if not query_upper.startswith(\\\"SELECT\\\"):\\n return False, \\\"Only SELECT queries allowed\\\"\\n\\n # Dangerous Keyword Blocklist\\n for keyword in Config.BLOCKED_KEYWORDS:\\n pattern = r'\\\\b' + re.escape(keyword) + r'\\\\b'\\n if re.search(pattern, query_upper):\\n return False, f\\\"Blocked keyword detected: {keyword}\\\"\\n\\n # Database Allowlist\\n if database not in Config.ALLOWED_DATABASES:\\n return False, f\\\"Database '{database}' not allowed\\\"\\n\\n # Max Rows prüfen\\n if max_rows < 1 or max_rows > Config.MAX_ROWS:\\n return False, f\\\"max_rows must be 1-{Config.MAX_ROWS}\\\"\\n\\n # Table Allowlist\\n from_tables = QueryValidator._extract_table_names(query_upper)\\n for table in from_tables:\\n if \\\"INFORMATION_SCHEMA\\\" in table:\\n continue\\n table_clean = table.split('.')[-1]\\n if table_clean not in [t.upper() for t in Config.ALLOWED_TABLES]:\\n return False, f\\\"Table '{table}' not allowed\\\"\\n\\n return True, \\\"\\\"<\/code><\/pre>\\n\\n<h3>Validierungsschritte (QueryValidator)<\/h3>\\n<table>\\n <tr><th>#<\/th><th>Prüfung<\/th><th>Fehler bei<\/th><\/tr>\\n <tr><td>1<\/td><td>Query nicht leer<\/td><td>Leere Query<\/td><\/tr>\\n <tr><td>2<\/td><td>Query-Länge<\/td><td>> 2000 Zeichen<\/td><\/tr>\\n <tr><td>3<\/td><td>SELECT-Only<\/td><td>Nicht mit SELECT beginnend<\/td><\/tr>\\n <tr><td>4<\/td><td>Keyword-Blocklist<\/td><td>Blockiertes Keyword gefunden<\/td><\/tr>\\n <tr><td>5<\/td><td>Database-Allowlist<\/td><td>Datenbank nicht erlaubt<\/td><\/tr>\\n <tr><td>6<\/td><td>Max-Rows<\/td><td>< 1 oder > 100<\/td><\/tr>\\n <tr><td>7<\/td><td>Table-Allowlist<\/td><td>Tabelle nicht erlaubt<\/td><\/tr>\\n<\/table>\\n\\n<h2>ExecuteValidator<\/h2>\\n<p>Validiert DDL-Statements für das <code>db_execute<\/code> Tool.<\/p>\\n\\n<pre><code>\\\"\\\"\\\"Execute Validator - Validierung für DDL\/DML Statements.\\\"\\\"\\\"\\nimport re\\nfrom config import Config\\n\\nclass ExecuteValidator:\\n \\\"\\\"\\\"Validiert DDL\/DML Statements gegen Sicherheitsregeln.\\\"\\\"\\\"\\n\\n # Erlaubte Statement-Typen\\n ALLOWED_STATEMENTS: list[str] = [\\\"ALTER\\\", \\\"CREATE\\\", \\\"DROP\\\", \\\"TRUNCATE\\\", \\\"SET\\\"]\\n\\n # Erlaubte SET-Variablen (Whitelist)\\n ALLOWED_SET_VARS: list[str] = [\\\"FOREIGN_KEY_CHECKS\\\"]\\n\\n # Verbotene Patterns (kritisch!)\\n FORBIDDEN_PATTERNS: list[str] = [\\n r\\\"\\\\bDROP\\\\s+DATABASE\\\\b\\\",\\n r\\\"\\\\bDROP\\\\s+SCHEMA\\\\b\\\",\\n r\\\"\\\\bCREATE\\\\s+DATABASE\\\\b\\\",\\n r\\\"\\\\bCREATE\\\\s+SCHEMA\\\\b\\\",\\n r\\\"\\\\bGRANT\\\\b\\\",\\n r\\\"\\\\bREVOKE\\\\b\\\",\\n r\\\"\\\\bSHUTDOWN\\\\b\\\",\\n ]\\n\\n # Verbotene Datenbanken (System-DBs)\\n FORBIDDEN_DATABASES: list[str] = [\\n \\\"information_schema\\\",\\n \\\"mysql\\\",\\n \\\"performance_schema\\\",\\n \\\"sys\\\",\\n ]\\n\\n @classmethod\\n def validate_statement(cls, statement: str, database: str) -> tuple[bool, str]:\\n \\\"\\\"\\\"\\n Validiert ein DDL\/DML Statement.\\n\\n Returns:\\n Tuple (is_valid, error_message)\\n \\\"\\\"\\\"\\n if not statement or len(statement.strip()) < 5:\\n return False, \\\"Statement must not be empty\\\"\\n\\n if len(statement) > Config.MAX_QUERY_LENGTH:\\n return False, f\\\"Statement exceeds max length\\\"\\n\\n statement_upper = statement.strip().upper()\\n\\n # Prüfe ob Statement mit erlaubtem Keyword beginnt\\n statement_type = cls._get_statement_type(statement_upper)\\n if statement_type is None:\\n return False, f\\\"Statement type not allowed. Allowed: {', '.join(cls.ALLOWED_STATEMENTS)}\\\"\\n\\n # Bei SET: nur erlaubte Variablen\\n if statement_type == \\\"SET\\\":\\n allowed = any(var in statement_upper for var in cls.ALLOWED_SET_VARS)\\n if not allowed:\\n return False, f\\\"SET variable not allowed. Allowed: {', '.join(cls.ALLOWED_SET_VARS)}\\\"\\n\\n # Prüfe verbotene Patterns\\n for pattern in cls.FORBIDDEN_PATTERNS:\\n if re.search(pattern, statement_upper):\\n return False, f\\\"Forbidden pattern detected\\\"\\n\\n # Prüfe Datenbank\\n if database not in Config.ALLOWED_DATABASES:\\n return False, f\\\"Database '{database}' not allowed\\\"\\n\\n # Prüfe ob Statement gegen System-DB zielt\\n for forbidden_db in cls.FORBIDDEN_DATABASES:\\n if re.search(rf\\\"\\\\b{forbidden_db}\\\\b\\\", statement_upper, re.IGNORECASE):\\n return False, f\\\"Operations on '{forbidden_db}' are forbidden\\\"\\n\\n return True, \\\"\\\"<\/code><\/pre>\\n\\n<h3>Validierungsschritte (ExecuteValidator)<\/h3>\\n<table>\\n <tr><th>#<\/th><th>Prüfung<\/th><th>Fehler bei<\/th><\/tr>\\n <tr><td>1<\/td><td>Statement nicht leer<\/td><td>Leeres Statement<\/td><\/tr>\\n <tr><td>2<\/td><td>Statement-Länge<\/td><td>> 2000 Zeichen<\/td><\/tr>\\n <tr><td>3<\/td><td>Statement-Typ<\/td><td>Nicht ALTER\/CREATE\/DROP\/TRUNCATE\/SET<\/td><\/tr>\\n <tr><td>4<\/td><td>SET-Variablen<\/td><td>Nicht in ALLOWED_SET_VARS<\/td><\/tr>\\n <tr><td>5<\/td><td>Forbidden Patterns<\/td><td>DROP DATABASE, GRANT, etc.<\/td><\/tr>\\n <tr><td>6<\/td><td>Database-Allowlist<\/td><td>Datenbank nicht erlaubt<\/td><\/tr>\\n <tr><td>7<\/td><td>System-DB-Schutz<\/td><td>mysql, information_schema, etc.<\/td><\/tr>\\n<\/table>\\n\\n<h3>Erlaubte DDL-Statements<\/h3>\\n<table>\\n <tr><th>Typ<\/th><th>Beispiel<\/th><th>Status<\/th><\/tr>\\n <tr><td>ALTER TABLE<\/td><td><code>ALTER TABLE tasks ADD COLUMN priority INT<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>CREATE TABLE<\/td><td><code>CREATE TABLE temp_data (...)<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>CREATE INDEX<\/td><td><code>CREATE INDEX idx_name ON table(col)<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>DROP TABLE<\/td><td><code>DROP TABLE temp_data<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>DROP INDEX<\/td><td><code>DROP INDEX idx_name ON table<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>TRUNCATE<\/td><td><code>TRUNCATE TABLE temp_data<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n <tr><td>SET<\/td><td><code>SET FOREIGN_KEY_CHECKS = 0<\/code><\/td><td>Erlaubt<\/td><\/tr>\\n<\/table>\\n\\n<h3>Verbotene Patterns<\/h3>\\n<table>\\n <tr><th>Pattern<\/th><th>Beschreibung<\/th><\/tr>\\n <tr><td>DROP DATABASE<\/td><td>Datenbank-Löschung verboten<\/td><\/tr>\\n <tr><td>DROP SCHEMA<\/td><td>Schema-Löschung verboten<\/td><\/tr>\\n <tr><td>CREATE DATABASE<\/td><td>Datenbank-Erstellung verboten<\/td><\/tr>\\n <tr><td>CREATE SCHEMA<\/td><td>Schema-Erstellung verboten<\/td><\/tr>\\n <tr><td>GRANT<\/td><td>Rechte-Vergabe verboten<\/td><\/tr>\\n <tr><td>REVOKE<\/td><td>Rechte-Entzug verboten<\/td><\/tr>\\n <tr><td>SHUTDOWN<\/td><td>Server-Shutdown verboten<\/td><\/tr>\\n<\/table>\\n\\n<h2>Keyword-Erkennung<\/h2>\\n<p>Keywords werden mit Word Boundaries erkannt:<\/p>\\n<pre><code># Regex-Pattern für Keyword \\\"DROP\\\"\\npattern = r'\\\\bDROP\\\\b'\\n\\n# Blockiert:\\n\\\"SELECT * FROM t; DROP TABLE t\\\" # DROP erkannt\\n\\n# Nicht blockiert (kein vollständiges Wort):\\n\\\"SELECT dropdown FROM t\\\" # DROP nicht erkannt<\/code><\/pre>\\n\\n<h2>Testfälle<\/h2>\\n<pre><code># QueryValidator - Muss DENIED returnen:\\n\\\"SELECT * FROM mcp_log; DROP TABLE mcp_log\\\" # DROP\\n\\\"SELECT LOAD_FILE('\/etc\/passwd')\\\" # LOAD_FILE\\n\\\"SELECT * FROM users\\\" # users nicht erlaubt\\n\\\"SELECT SLEEP(10)\\\" # SLEEP\\n\\n# ExecuteValidator - Muss DENIED returnen:\\n\\\"DROP DATABASE ki_dev\\\" # Forbidden Pattern\\n\\\"GRANT ALL ON ki_dev.* TO user\\\" # GRANT verboten\\n\\\"ALTER TABLE mysql.user ADD COLUMN x INT\\\" # System-DB\\n\\n# ExecuteValidator - Muss SUCCESS returnen:\\n\\\"ALTER TABLE tasks ADD COLUMN priority INT\\\" # Erlaubt\\n\\\"CREATE INDEX idx_status ON tasks(status)\\\" # Erlaubt\\n\\\"SET FOREIGN_KEY_CHECKS = 0\\\" # Erlaubte Variable<\/code><\/pre>\\n\\n<h2>Verwandte Kapitel<\/h2>\\n<ul>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db-config\\\">Konfiguration<\/a> - Allowlists und Blocklists<\/li>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db-security\\\">Sicherheit<\/a> - Gesamtkonzept<\/li>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db-tools\\\">Tools<\/a> - db_select und db_execute<\/li>\\n<\/ul>\",\n \"status\": \"published\",\n \"sort_order\": 7,\n \"depth\": 2,\n \"created_at\": \"2025-12-20T11:13:58\",\n \"updated_at\": \"2025-12-31T05:06:46\"\n },\n \"message\": \"Document #43 updated\"\n}"
}
]
}