diff --git a/modules/web_viewer/app.py b/modules/web_viewer/app.py index b633a1a..6174026 100644 --- a/modules/web_viewer/app.py +++ b/modules/web_viewer/app.py @@ -24,6 +24,7 @@ sys.path.insert(0, project_root) from modules.db_manager import DBManager from modules.repeater_manager import RepeaterManager +from modules.security_utils import validate_safe_path class BotDataViewer: """Complete web interface using Flask-SocketIO 5.x best practices""" @@ -178,6 +179,13 @@ class BotDataViewer: # Get database path from config db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError as e: + self.logger.warning(f"Invalid database path: {e}, using default: bot_data.db") + db_path = 'bot_data.db' + # Connect to database and create table if it doesn't exist conn = sqlite3.connect(db_path, timeout=30) cursor = conn.cursor() @@ -388,6 +396,13 @@ class BotDataViewer: # Get database path db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass + conn = sqlite3.connect(db_path, timeout=30) cursor = conn.cursor() @@ -1413,6 +1428,13 @@ class BotDataViewer: # Get database path db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass + # Connect to database with timeout to prevent hanging conn = sqlite3.connect(db_path, timeout=30) cursor = conn.cursor() @@ -1525,6 +1547,13 @@ class BotDataViewer: # Get database path db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass + # Use timeout to prevent hanging conn = sqlite3.connect(db_path, timeout=30) cursor = conn.cursor() @@ -2004,6 +2033,12 @@ class BotDataViewer: # Get database file size import os db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass try: db_size_bytes = os.path.getsize(db_path) if db_size_bytes < 1024: @@ -2060,6 +2095,12 @@ class BotDataViewer: # Get initial database size import os db_path = self.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + db_path = str(validate_safe_path(db_path, base_dir=str(self.bot_root), allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass initial_size = os.path.getsize(db_path) # Perform VACUUM to reclaim unused space diff --git a/modules/web_viewer/integration.py b/modules/web_viewer/integration.py index 0191b33..b1401c0 100644 --- a/modules/web_viewer/integration.py +++ b/modules/web_viewer/integration.py @@ -11,6 +11,7 @@ import sys import os import re from pathlib import Path +from ..security_utils import validate_safe_path class BotIntegration: """Simple bot integration for web viewer compatibility""" @@ -36,6 +37,14 @@ class BotIntegration: # Get database path from config db_path = self.bot.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + base_dir = str(self.bot.bot_root) if hasattr(self.bot, 'bot_root') else '.' + db_path = str(validate_safe_path(db_path, base_dir=base_dir, allow_absolute=False)) + except ValueError as e: + self.bot.logger.warning(f"Invalid database path: {e}, using default: bot_data.db") + db_path = 'bot_data.db' + # Connect to database and create table if it doesn't exist conn = sqlite3.connect(db_path) cursor = conn.cursor() @@ -99,6 +108,13 @@ class BotIntegration: # Store in database for web viewer to read db_path = self.bot.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + base_dir = str(self.bot.bot_root) if hasattr(self.bot, 'bot_root') else '.' + db_path = str(validate_safe_path(db_path, base_dir=base_dir, allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass conn = sqlite3.connect(db_path) cursor = conn.cursor() @@ -149,6 +165,13 @@ class BotIntegration: # Store in database for web viewer to read db_path = self.bot.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + base_dir = str(self.bot.bot_root) if hasattr(self.bot, 'bot_root') else '.' + db_path = str(validate_safe_path(db_path, base_dir=base_dir, allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass conn = sqlite3.connect(db_path) cursor = conn.cursor() @@ -176,6 +199,13 @@ class BotIntegration: # Store in database for web viewer to read db_path = self.bot.config.get('Database', 'path', fallback='bot_data.db') + # Validate and resolve database path relative to bot root + try: + base_dir = str(self.bot.bot_root) if hasattr(self.bot, 'bot_root') else '.' + db_path = str(validate_safe_path(db_path, base_dir=base_dir, allow_absolute=False)) + except ValueError: + # If validation fails, use default (already set above) + pass conn = sqlite3.connect(db_path) cursor = conn.cursor()