From 7f95c76c18b796f6c3e7688188677eda1ac6e876 Mon Sep 17 00:00:00 2001 From: Chuck Date: Sat, 21 Mar 2026 13:39:20 -0400 Subject: [PATCH] fix(security): fix plugin update logging and config validation leak - update_plugin: change logger.exception to logger.error in non-except branch (logger.exception outside an except block logs useless "NoneType: None" traceback) - update_plugin: remove duplicate logger.exception call in except block (was logging the same failure twice) - save_plugin_config validation: stop logging full plugin_config dict (can contain API keys, passwords, tokens) and raw form_data values; log only keys and validation errors instead Co-Authored-By: Claude Opus 4.6 --- web_interface/blueprints/api_v3.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/web_interface/blueprints/api_v3.py b/web_interface/blueprints/api_v3.py index 9e332f73..16b65a1b 100644 --- a/web_interface/blueprints/api_v3.py +++ b/web_interface/blueprints/api_v3.py @@ -2719,8 +2719,8 @@ def update_plugin(): } ) - logger.exception("[PluginUpdate] Update failed for %s: %s", plugin_id, error_msg) - + logger.error("[PluginUpdate] Update failed for %s: %s", plugin_id, error_msg) + return error_response( ErrorCode.PLUGIN_UPDATE_FAILED, error_msg, @@ -2729,8 +2729,7 @@ def update_plugin(): except Exception as e: logger.exception("[PluginUpdate] Exception in update_plugin endpoint") - - logger.exception("[PluginUpdate] Unhandled exception") + from src.web_interface.errors import WebInterfaceError error = WebInterfaceError.from_exception(e, ErrorCode.PLUGIN_UPDATE_FAILED) if api_v3.operation_history: @@ -4566,15 +4565,17 @@ def save_plugin_config(): if not is_valid: # Log validation errors for debugging logger.error(f"Config validation failed for {plugin_id}") - logger.error(f"Validation errors: {validation_errors}") - logger.error(f"Config that failed: {plugin_config}") - logger.error(f"Schema properties: {list(enhanced_schema.get('properties', {}).keys())}") - - # Log raw form data if this was a form submission + logger.error( + "[PluginConfig] Validation errors: %s | config keys: %s | schema keys: %s", + validation_errors, + list(plugin_config.keys()), + list(enhanced_schema.get('properties', {}).keys()), + ) if 'application/json' not in (request.content_type or ''): - form_data = request.form.to_dict() - logger.error("[PluginConfig] Raw form data: %s", json.dumps({k: str(v)[:200] for k, v in form_data.items()}, indent=2)) - logger.error("[PluginConfig] Parsed config: %s", json.dumps(plugin_config, indent=2, default=str)) + logger.error( + "[PluginConfig] Form field keys: %s", + list(request.form.keys()), + ) return error_response( ErrorCode.CONFIG_VALIDATION_FAILED, 'Configuration validation failed',