{
"event": "PreToolUse",
"tool_name": "mcp__mcp-docs__docs_update",
"tool_input": {
"id": 40,
"content": "<nav class=\"breadcrumb\">\n <a href=\"\/docs\">Dokumentation<\/a> » <a href=\"\/docs\/mcp\/mcp-db\">MCP-DB<\/a> » Sicherheit\n<\/nav>\n\n<h1>MCP-DB Sicherheit<\/h1>\n<p>Vollständige Sicherheitsmaßnahmen und DB-User Hardening.<\/p>\n\n<h2>Sicherheitsübersicht<\/h2>\n<table>\n <tr><th>Maßnahme<\/th><th>Implementierung<\/th><th>Verifiziert<\/th><\/tr>\n <tr><td>Nur SELECT<\/td><td>QueryValidator.validate_query()<\/td><td>Ja<\/td><\/tr>\n <tr><td>Prepared Statements<\/td><td>cursor.execute(query, params)<\/td><td>Ja<\/td><\/tr>\n <tr><td>Keyword Blocklist<\/td><td>15 Keywords mit Word Boundaries<\/td><td>Ja<\/td><\/tr>\n <tr><td>Database Allowlist<\/td><td>ki_protokoll, ki_system<\/td><td>Ja<\/td><\/tr>\n <tr><td>Table Allowlist<\/td><td>Konfigurierbar in Config<\/td><td>Ja<\/td><\/tr>\n <tr><td>Query Timeout<\/td><td>30 Sekunden (MAX_EXECUTION_TIME)<\/td><td>Ja<\/td><\/tr>\n <tr><td>Row Limit<\/td><td>Max 100<\/td><td>Ja<\/td><\/tr>\n <tr><td>Query Length<\/td><td>Max 2000 Zeichen<\/td><td>Ja<\/td><\/tr>\n <tr><td>Separate DB-User<\/td><td>mcp_readonly, mcp_logger<\/td><td>Ja<\/td><\/tr>\n <tr><td>Logging<\/td><td>Jede Operation in mcp_log<\/td><td>Ja<\/td><\/tr>\n <tr><td>Credentials<\/td><td>.env (chmod 600)<\/td><td>Ja<\/td><\/tr>\n <tr><td>Fail-Safe<\/td><td>Exception bei Logging-Fehler<\/td><td>Ja<\/td><\/tr>\n <tr><td><strong>Blocking-Hook<\/strong><\/td><td><strong>PreToolUse Hook für Bash<\/strong><\/td><td><strong>Ja<\/strong><\/td><\/tr>\n<\/table>\n\n<h2>Blocking-Hook (PreToolUse)<\/h2>\n<p class=\"alert alert-danger\"><strong>KRITISCH:<\/strong> Direkte mysql\/mariadb-Befehle mit Passwörtern werden auf System-Ebene blockiert!<\/p>\n\n<h3>Funktionsweise<\/h3>\n<p>Der Hook <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py<\/code> wird vor jedem Bash-Befehl ausgeführt und blockiert gefährliche Datenbankzugriffe:<\/p>\n\n<table>\n <tr><th>Komponente<\/th><th>Beschreibung<\/th><\/tr>\n <tr><td>Trigger<\/td><td>PreToolUse Hook für alle Bash-Befehle<\/td><\/tr>\n <tr><td>Exit Code 2<\/td><td>Blockiert den Befehl (Claude Code Standard)<\/td><\/tr>\n <tr><td>Fehlermeldung<\/td><td>Ausgabe auf stderr mit MCP-DB Verweis<\/td><\/tr>\n<\/table>\n\n<h3>Blockierte Muster<\/h3>\n<pre><code># Blockierte Befehle (Beispiele)\nmysql -u root -pPassword123 -e \"SELECT 1\"\nmariadb -u user -pSecret\nmysql --password=geheim --execute=\"DROP TABLE users\"\nmysqldump ki_protokoll > backup.sql\nsudo mysql -u root -pPass\n\n# Stattdessen verwenden:\nmcp__mcp-db__db_select - für SELECT-Abfragen\nmcp__mcp-db__db_schema - für Tabellenstruktur\nmcp__mcp-db__db_stats - für Statistiken<\/code><\/pre>\n\n<h3>Hook-Konfiguration<\/h3>\n<p>Der Hook ist in <code>\/var\/www\/.claude\/settings.local.json<\/code> konfiguriert:<\/p>\n\n<pre><code>{\n \"hooks\": {\n \"PreToolUse\": [\n {\n \"matcher\": \"Bash\",\n \"hooks\": [\n {\n \"type\": \"command\",\n \"command\": \"\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\",\n \"timeout\": 5\n }\n ]\n }\n ]\n }\n}<\/code><\/pre>\n\n<h3>Hook-Skript<\/h3>\n<p>Pfad: <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py<\/code><\/p>\n\n<pre><code>#!\/usr\/bin\/env python3\n\"\"\"PreToolUse Hook - Blockiert direkte DB-Zugriffe\"\"\"\nimport sys\nimport json\nimport re\n\nBLOCKED_PATTERNS = [\n r'\\bmysql\\s+-[up]', # mysql -u oder -p\n r'\\bmariadb\\s+-[up]', # mariadb -u oder -p\n r'--password=', # --password=xxx\n r'\\bmysqldump\\b', # mysqldump\n r'-p[A-Za-z0-9]', # -pPassword (ohne Leerzeichen)\n r'\\bsudo\\s+mysql\\b', # sudo mysql\n r'\\bsudo\\s+mariadb\\b', # sudo mariadb\n]\n\ndef main():\n try:\n data = json.load(sys.stdin)\n if data.get(\"tool_name\") != \"Bash\":\n sys.exit(0) # Erlauben\n \n command = data.get(\"tool_input\", {}).get(\"command\", \"\")\n \n for pattern in BLOCKED_PATTERNS:\n if re.search(pattern, command, re.IGNORECASE):\n print(\"BLOCKIERT: Direkter Datenbankzugriff ist verboten!\", file=sys.stderr)\n print(\"\\nVerwende stattdessen MCP-DB:\", file=sys.stderr)\n print(\"- mcp__mcp-db__db_select - für SELECT-Abfragen\", file=sys.stderr)\n print(\"- mcp__mcp-db__db_schema - für Tabellenstruktur\", file=sys.stderr)\n print(\"- mcp__mcp-db__db_stats - für Statistiken\", file=sys.stderr)\n print(\"\\nNIEMALS Passwörter in Bash-Befehlen verwenden!\", file=sys.stderr)\n sys.exit(2) # Exit Code 2 = BLOCK\n \n sys.exit(0) # Erlauben\n except Exception:\n sys.exit(0) # Fail-Open bei Fehlern\n\nif __name__ == \"__main__\":\n main()<\/code><\/pre>\n\n<h3>Hook testen<\/h3>\n<pre><code># Test: Blockierter Befehl\necho '{\"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"mysql -u root -ptest\"}}' | \\\n \/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\necho \"Exit code: $?\"\n# Erwartung: Exit code 2, Fehlermeldung auf stderr\n\n# Test: Erlaubter Befehl\necho '{\"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"ls -la\"}}' | \\\n \/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\necho \"Exit code: $?\"\n# Erwartung: Exit code 0 (erlaubt)<\/code><\/pre>\n\n<h2>Sicherheitsschichten (Defense in Depth)<\/h2>\n<p>Mehrere Schutzmechanismen arbeiten zusammen:<\/p>\n<table>\n <tr><th>Schicht<\/th><th>Mechanismus<\/th><th>Schutz vor<\/th><\/tr>\n <tr>\n <td><strong>1. Claude Code Hook<\/strong><\/td>\n <td>block_direct_db.py (Exit Code 2)<\/td>\n <td>Direkte Bash-Befehle mit mysql\/mariadb<\/td>\n <\/tr>\n <tr>\n <td>2. MCP-DB Validator<\/td>\n <td>QueryValidator.validate_query()<\/td>\n <td>SQL-Injection, unerlaubte Keywords<\/td>\n <\/tr>\n <tr>\n <td>3. DB-User Rechte<\/td>\n <td>mcp_readonly (nur SELECT)<\/td>\n <td>Datenmanipulation, DDL\/DCL<\/td>\n <\/tr>\n <tr>\n <td>4. Table Allowlist<\/td>\n <td>Config.ALLOWED_TABLES<\/td>\n <td>Zugriff auf nicht-öffentliche Tabellen<\/td>\n <\/tr>\n <tr>\n <td>5. Audit-Log<\/td>\n <td>mcp_log Tabelle<\/td>\n <td>Nachvollziehbarkeit, Incident Response<\/td>\n <\/tr>\n<\/table>\n\n<h2>DB-User Hardening<\/h2>\n\n<h3>mcp_readonly (Query-User)<\/h3>\n<p>Nur SELECT auf spezifische Tabellen:<\/p>\n<pre><code>-- User erstellen\nCREATE USER IF NOT EXISTS 'mcp_readonly'@'localhost'\nIDENTIFIED BY 'SECURE_PASSWORD_HERE';\n\n-- Nur SELECT auf erlaubte Tabellen in ki_protokoll\nGRANT SELECT ON ki_protokoll.mcp_log TO 'mcp_readonly'@'localhost';\nGRANT SELECT ON ki_protokoll.ki_eintraege TO 'mcp_readonly'@'localhost';\nGRANT SELECT ON ki_protokoll.ki_kategorien TO 'mcp_readonly'@'localhost';\nGRANT SELECT ON ki_protokoll.ki_tags TO 'mcp_readonly'@'localhost';\nGRANT SELECT ON ki_protokoll.ki_settings TO 'mcp_readonly'@'localhost';\n\n-- Schema-Zugriff für db_schema Tool\nGRANT SELECT ON information_schema.TABLES TO 'mcp_readonly'@'localhost';\n\n-- ki_system (nach Bedarf)\nGRANT SELECT ON ki_system.* TO 'mcp_readonly'@'localhost';\n\nFLUSH PRIVILEGES;<\/code><\/pre>\n\n<h3>mcp_logger (Logging-User)<\/h3>\n<p>Nur INSERT auf mcp_log:<\/p>\n<pre><code>-- User erstellen\nCREATE USER IF NOT EXISTS 'mcp_logger'@'localhost'\nIDENTIFIED BY 'DIFFERENT_SECURE_PASSWORD_HERE';\n\n-- Nur INSERT auf mcp_log\nGRANT INSERT ON ki_protokoll.mcp_log TO 'mcp_logger'@'localhost';\n\nFLUSH PRIVILEGES;<\/code><\/pre>\n\n<h2>Keyword Blocklist<\/h2>\n<table>\n <tr><th>Kategorie<\/th><th>Keywords<\/th><th>Risiko<\/th><\/tr>\n <tr><td>DML<\/td><td>DELETE, INSERT, UPDATE<\/td><td>Datenmanipulation<\/td><\/tr>\n <tr><td>DDL<\/td><td>DROP, TRUNCATE, ALTER, CREATE, RENAME<\/td><td>Strukturänderung<\/td><\/tr>\n <tr><td>DCL<\/td><td>GRANT, REVOKE<\/td><td>Rechteänderung<\/td><\/tr>\n <tr><td>File-Ops<\/td><td>LOAD_FILE, INTO OUTFILE, INTO DUMPFILE<\/td><td>Dateizugriff<\/td><\/tr>\n <tr><td>DoS<\/td><td>BENCHMARK, SLEEP<\/td><td>Resource Exhaustion<\/td><\/tr>\n<\/table>\n\n<h2>Credential-Management<\/h2>\n\n<h3>.env Datei<\/h3>\n<pre><code># Berechtigungen setzen\nchmod 600 \/opt\/mcp-servers\/mcp-db\/.env\nchown root:root \/opt\/mcp-servers\/mcp-db\/.env<\/code><\/pre>\n\n<h3>Keine Credentials in Claude Config<\/h3>\n<pre><code># Registrierung OHNE Credentials\nclaude mcp add mcp-db \\\n --transport stdio \\\n -- \/opt\/mcp-servers\/mcp-db\/venv\/bin\/python \\\n \/opt\/mcp-servers\/mcp-db\/server.py\n\n# Credentials werden aus .env geladen, nicht aus dem Befehl<\/code><\/pre>\n\n<h2>Incident Response<\/h2>\n<table>\n <tr><th>Event<\/th><th>Indikator<\/th><th>Maßnahme<\/th><\/tr>\n <tr>\n <td>Hook blockiert Befehl<\/td>\n <td>PreToolUse:Bash hook error: BLOCKIERT<\/td>\n <td>MCP-DB Tools verwenden<\/td>\n <\/tr>\n <tr>\n <td>SQL Injection Versuch<\/td>\n <td>status='denied', Keyword in error_message<\/td>\n <td>Log analysieren, ggf. Blocklist erweitern<\/td>\n <\/tr>\n <tr>\n <td>Unbekannte Tabelle<\/td>\n <td>status='denied', \"Table not allowed\"<\/td>\n <td>Allowlist prüfen oder erweitern<\/td>\n <\/tr>\n <tr>\n <td>Timeout<\/td>\n <td>status='error', Query > 30s<\/td>\n <td>Query optimieren oder Timeout erhöhen<\/td>\n <\/tr>\n<\/table>\n\n<h2>Verwandte Kapitel<\/h2>\n<ul>\n <li><a href=\"\/docs\/mcp\/mcp-db\/mcp-db-config\">Konfiguration<\/a> - Allowlists und Hook-Config<\/li>\n <li><a href=\"\/docs\/mcp\/mcp-db\/mcp-db-validators\">Validators<\/a> - Implementierung<\/li>\n <li><a href=\"\/docs\/mcp\/mcp-db\/mcp-db-cheatsheet\">Cheat-Sheet<\/a> - Migration von mysql zu MCP-DB<\/li>\n <li><a href=\"\/docs\/betrieb\/claude-hooks\">Claude Hooks<\/a> - Allgemeine Hook-Dokumentation<\/li>\n<\/ul>"
}
}
{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 40,\n \"parent_id\": 36,\n \"slug\": \"mcp-db-security\",\n \"path\": \"\/mcp\/mcp-db\/mcp-db-security\",\n \"title\": \"Sicherheit\",\n \"description\": \"Vollständige Sicherheitsmaßnahmen und DB-User Hardening.\",\n \"content\": \"<nav class=\\\"breadcrumb\\\">\\n <a href=\\\"\/docs\\\">Dokumentation<\/a> » <a href=\\\"\/docs\/mcp\/mcp-db\\\">MCP-DB<\/a> » Sicherheit\\n<\/nav>\\n\\n<h1>MCP-DB Sicherheit<\/h1>\\n<p>Vollständige Sicherheitsmaßnahmen und DB-User Hardening.<\/p>\\n\\n<h2>Sicherheitsübersicht<\/h2>\\n<table>\\n <tr><th>Maßnahme<\/th><th>Implementierung<\/th><th>Verifiziert<\/th><\/tr>\\n <tr><td>Nur SELECT<\/td><td>QueryValidator.validate_query()<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Prepared Statements<\/td><td>cursor.execute(query, params)<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Keyword Blocklist<\/td><td>15 Keywords mit Word Boundaries<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Database Allowlist<\/td><td>ki_protokoll, ki_system<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Table Allowlist<\/td><td>Konfigurierbar in Config<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Query Timeout<\/td><td>30 Sekunden (MAX_EXECUTION_TIME)<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Row Limit<\/td><td>Max 100<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Query Length<\/td><td>Max 2000 Zeichen<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Separate DB-User<\/td><td>mcp_readonly, mcp_logger<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Logging<\/td><td>Jede Operation in mcp_log<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Credentials<\/td><td>.env (chmod 600)<\/td><td>Ja<\/td><\/tr>\\n <tr><td>Fail-Safe<\/td><td>Exception bei Logging-Fehler<\/td><td>Ja<\/td><\/tr>\\n <tr><td><strong>Blocking-Hook<\/strong><\/td><td><strong>PreToolUse Hook für Bash<\/strong><\/td><td><strong>Ja<\/strong><\/td><\/tr>\\n<\/table>\\n\\n<h2>Blocking-Hook (PreToolUse)<\/h2>\\n<p class=\\\"alert alert-danger\\\"><strong>KRITISCH:<\/strong> Direkte mysql\/mariadb-Befehle mit Passwörtern werden auf System-Ebene blockiert!<\/p>\\n\\n<h3>Funktionsweise<\/h3>\\n<p>Der Hook <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py<\/code> wird vor jedem Bash-Befehl ausgeführt und blockiert gefährliche Datenbankzugriffe:<\/p>\\n\\n<table>\\n <tr><th>Komponente<\/th><th>Beschreibung<\/th><\/tr>\\n <tr><td>Trigger<\/td><td>PreToolUse Hook für alle Bash-Befehle<\/td><\/tr>\\n <tr><td>Exit Code 2<\/td><td>Blockiert den Befehl (Claude Code Standard)<\/td><\/tr>\\n <tr><td>Fehlermeldung<\/td><td>Ausgabe auf stderr mit MCP-DB Verweis<\/td><\/tr>\\n<\/table>\\n\\n<h3>Blockierte Muster<\/h3>\\n<pre><code># Blockierte Befehle (Beispiele)\\nmysql -u root -pPassword123 -e \\\"SELECT 1\\\"\\nmariadb -u user -pSecret\\nmysql --password=geheim --execute=\\\"DROP TABLE users\\\"\\nmysqldump ki_protokoll > backup.sql\\nsudo mysql -u root -pPass\\n\\n# Stattdessen verwenden:\\nmcp__mcp-db__db_select - für SELECT-Abfragen\\nmcp__mcp-db__db_schema - für Tabellenstruktur\\nmcp__mcp-db__db_stats - für Statistiken<\/code><\/pre>\\n\\n<h3>Hook-Konfiguration<\/h3>\\n<p>Der Hook ist in <code>\/var\/www\/.claude\/settings.local.json<\/code> konfiguriert:<\/p>\\n\\n<pre><code>{\\n \\\"hooks\\\": {\\n \\\"PreToolUse\\\": [\\n {\\n \\\"matcher\\\": \\\"Bash\\\",\\n \\\"hooks\\\": [\\n {\\n \\\"type\\\": \\\"command\\\",\\n \\\"command\\\": \\\"\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\\\",\\n \\\"timeout\\\": 5\\n }\\n ]\\n }\\n ]\\n }\\n}<\/code><\/pre>\\n\\n<h3>Hook-Skript<\/h3>\\n<p>Pfad: <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py<\/code><\/p>\\n\\n<pre><code>#!\/usr\/bin\/env python3\\n\\\"\\\"\\\"PreToolUse Hook - Blockiert direkte DB-Zugriffe\\\"\\\"\\\"\\nimport sys\\nimport json\\nimport re\\n\\nBLOCKED_PATTERNS = [\\n r'\\\\bmysql\\\\s+-[up]', # mysql -u oder -p\\n r'\\\\bmariadb\\\\s+-[up]', # mariadb -u oder -p\\n r'--password=', # --password=xxx\\n r'\\\\bmysqldump\\\\b', # mysqldump\\n r'-p[A-Za-z0-9]', # -pPassword (ohne Leerzeichen)\\n r'\\\\bsudo\\\\s+mysql\\\\b', # sudo mysql\\n r'\\\\bsudo\\\\s+mariadb\\\\b', # sudo mariadb\\n]\\n\\ndef main():\\n try:\\n data = json.load(sys.stdin)\\n if data.get(\\\"tool_name\\\") != \\\"Bash\\\":\\n sys.exit(0) # Erlauben\\n \\n command = data.get(\\\"tool_input\\\", {}).get(\\\"command\\\", \\\"\\\")\\n \\n for pattern in BLOCKED_PATTERNS:\\n if re.search(pattern, command, re.IGNORECASE):\\n print(\\\"BLOCKIERT: Direkter Datenbankzugriff ist verboten!\\\", file=sys.stderr)\\n print(\\\"\\\\nVerwende stattdessen MCP-DB:\\\", file=sys.stderr)\\n print(\\\"- mcp__mcp-db__db_select - für SELECT-Abfragen\\\", file=sys.stderr)\\n print(\\\"- mcp__mcp-db__db_schema - für Tabellenstruktur\\\", file=sys.stderr)\\n print(\\\"- mcp__mcp-db__db_stats - für Statistiken\\\", file=sys.stderr)\\n print(\\\"\\\\nNIEMALS Passwörter in Bash-Befehlen verwenden!\\\", file=sys.stderr)\\n sys.exit(2) # Exit Code 2 = BLOCK\\n \\n sys.exit(0) # Erlauben\\n except Exception:\\n sys.exit(0) # Fail-Open bei Fehlern\\n\\nif __name__ == \\\"__main__\\\":\\n main()<\/code><\/pre>\\n\\n<h3>Hook testen<\/h3>\\n<pre><code># Test: Blockierter Befehl\\necho '{\\\"tool_name\\\": \\\"Bash\\\", \\\"tool_input\\\": {\\\"command\\\": \\\"mysql -u root -ptest\\\"}}' | \\\\\\n \/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\\necho \\\"Exit code: $?\\\"\\n# Erwartung: Exit code 2, Fehlermeldung auf stderr\\n\\n# Test: Erlaubter Befehl\\necho '{\\\"tool_name\\\": \\\"Bash\\\", \\\"tool_input\\\": {\\\"command\\\": \\\"ls -la\\\"}}' | \\\\\\n \/var\/www\/tools\/ki-protokoll\/claude-hook\/block_direct_db.py\\necho \\\"Exit code: $?\\\"\\n# Erwartung: Exit code 0 (erlaubt)<\/code><\/pre>\\n\\n<h2>Sicherheitsschichten (Defense in Depth)<\/h2>\\n<p>Mehrere Schutzmechanismen arbeiten zusammen:<\/p>\\n<table>\\n <tr><th>Schicht<\/th><th>Mechanismus<\/th><th>Schutz vor<\/th><\/tr>\\n <tr>\\n <td><strong>1. Claude Code Hook<\/strong><\/td>\\n <td>block_direct_db.py (Exit Code 2)<\/td>\\n <td>Direkte Bash-Befehle mit mysql\/mariadb<\/td>\\n <\/tr>\\n <tr>\\n <td>2. MCP-DB Validator<\/td>\\n <td>QueryValidator.validate_query()<\/td>\\n <td>SQL-Injection, unerlaubte Keywords<\/td>\\n <\/tr>\\n <tr>\\n <td>3. DB-User Rechte<\/td>\\n <td>mcp_readonly (nur SELECT)<\/td>\\n <td>Datenmanipulation, DDL\/DCL<\/td>\\n <\/tr>\\n <tr>\\n <td>4. Table Allowlist<\/td>\\n <td>Config.ALLOWED_TABLES<\/td>\\n <td>Zugriff auf nicht-öffentliche Tabellen<\/td>\\n <\/tr>\\n <tr>\\n <td>5. Audit-Log<\/td>\\n <td>mcp_log Tabelle<\/td>\\n <td>Nachvollziehbarkeit, Incident Response<\/td>\\n <\/tr>\\n<\/table>\\n\\n<h2>DB-User Hardening<\/h2>\\n\\n<h3>mcp_readonly (Query-User)<\/h3>\\n<p>Nur SELECT auf spezifische Tabellen:<\/p>\\n<pre><code>-- User erstellen\\nCREATE USER IF NOT EXISTS 'mcp_readonly'@'localhost'\\nIDENTIFIED BY 'SECURE_PASSWORD_HERE';\\n\\n-- Nur SELECT auf erlaubte Tabellen in ki_protokoll\\nGRANT SELECT ON ki_protokoll.mcp_log TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_eintraege TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_kategorien TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_tags TO 'mcp_readonly'@'localhost';\\nGRANT SELECT ON ki_protokoll.ki_settings TO 'mcp_readonly'@'localhost';\\n\\n-- Schema-Zugriff für db_schema Tool\\nGRANT SELECT ON information_schema.TABLES TO 'mcp_readonly'@'localhost';\\n\\n-- ki_system (nach Bedarf)\\nGRANT SELECT ON ki_system.* TO 'mcp_readonly'@'localhost';\\n\\nFLUSH PRIVILEGES;<\/code><\/pre>\\n\\n<h3>mcp_logger (Logging-User)<\/h3>\\n<p>Nur INSERT auf mcp_log:<\/p>\\n<pre><code>-- User erstellen\\nCREATE USER IF NOT EXISTS 'mcp_logger'@'localhost'\\nIDENTIFIED BY 'DIFFERENT_SECURE_PASSWORD_HERE';\\n\\n-- Nur INSERT auf mcp_log\\nGRANT INSERT ON ki_protokoll.mcp_log TO 'mcp_logger'@'localhost';\\n\\nFLUSH PRIVILEGES;<\/code><\/pre>\\n\\n<h2>Keyword Blocklist<\/h2>\\n<table>\\n <tr><th>Kategorie<\/th><th>Keywords<\/th><th>Risiko<\/th><\/tr>\\n <tr><td>DML<\/td><td>DELETE, INSERT, UPDATE<\/td><td>Datenmanipulation<\/td><\/tr>\\n <tr><td>DDL<\/td><td>DROP, TRUNCATE, ALTER, CREATE, RENAME<\/td><td>Strukturänderung<\/td><\/tr>\\n <tr><td>DCL<\/td><td>GRANT, REVOKE<\/td><td>Rechteänderung<\/td><\/tr>\\n <tr><td>File-Ops<\/td><td>LOAD_FILE, INTO OUTFILE, INTO DUMPFILE<\/td><td>Dateizugriff<\/td><\/tr>\\n <tr><td>DoS<\/td><td>BENCHMARK, SLEEP<\/td><td>Resource Exhaustion<\/td><\/tr>\\n<\/table>\\n\\n<h2>Credential-Management<\/h2>\\n\\n<h3>.env Datei<\/h3>\\n<pre><code># Berechtigungen setzen\\nchmod 600 \/opt\/mcp-servers\/mcp-db\/.env\\nchown root:root \/opt\/mcp-servers\/mcp-db\/.env<\/code><\/pre>\\n\\n<h3>Keine Credentials in Claude Config<\/h3>\\n<pre><code># Registrierung OHNE Credentials\\nclaude mcp add mcp-db \\\\\\n --transport stdio \\\\\\n -- \/opt\/mcp-servers\/mcp-db\/venv\/bin\/python \\\\\\n \/opt\/mcp-servers\/mcp-db\/server.py\\n\\n# Credentials werden aus .env geladen, nicht aus dem Befehl<\/code><\/pre>\\n\\n<h2>Incident Response<\/h2>\\n<table>\\n <tr><th>Event<\/th><th>Indikator<\/th><th>Maßnahme<\/th><\/tr>\\n <tr>\\n <td>Hook blockiert Befehl<\/td>\\n <td>PreToolUse:Bash hook error: BLOCKIERT<\/td>\\n <td>MCP-DB Tools verwenden<\/td>\\n <\/tr>\\n <tr>\\n <td>SQL Injection Versuch<\/td>\\n <td>status='denied', Keyword in error_message<\/td>\\n <td>Log analysieren, ggf. Blocklist erweitern<\/td>\\n <\/tr>\\n <tr>\\n <td>Unbekannte Tabelle<\/td>\\n <td>status='denied', \\\"Table not allowed\\\"<\/td>\\n <td>Allowlist prüfen oder erweitern<\/td>\\n <\/tr>\\n <tr>\\n <td>Timeout<\/td>\\n <td>status='error', Query > 30s<\/td>\\n <td>Query optimieren oder Timeout erhöhen<\/td>\\n <\/tr>\\n<\/table>\\n\\n<h2>Verwandte Kapitel<\/h2>\\n<ul>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db\/mcp-db-config\\\">Konfiguration<\/a> - Allowlists und Hook-Config<\/li>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db\/mcp-db-validators\\\">Validators<\/a> - Implementierung<\/li>\\n <li><a href=\\\"\/docs\/mcp\/mcp-db\/mcp-db-cheatsheet\\\">Cheat-Sheet<\/a> - Migration von mysql ... [TRUNCATED-94b31ff4f72b723b]"
}
]
}