From 9593da5fe304a04458106d5a324643e8e0c016aa Mon Sep 17 00:00:00 2001 From: Amxnnn Date: Mon, 11 Aug 2025 08:16:44 +0530 Subject: [PATCH] Fix insecure error handling to prevent information disclosure - Implement safe error message mapping to prevent sensitive information exposure - Add debug mode check to only show detailed errors in development - Return generic error messages in production to prevent information disclosure - Log detailed errors internally for debugging while showing safe messages to users - Fixes security vulnerability reported in issue #1 This change prevents attackers from gathering information about the application's internal structure through error messages while maintaining debugging capabilities in development environments. --- frontend/src/utils/error.ts | 52 +++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/frontend/src/utils/error.ts b/frontend/src/utils/error.ts index d06aa247..6b45e7bd 100644 --- a/frontend/src/utils/error.ts +++ b/frontend/src/utils/error.ts @@ -38,26 +38,62 @@ export function extractErrorMessage(e: any): string | null { return null; } +// Safe error messages that don't expose sensitive information +const SAFE_ERROR_MESSAGES: Record = { + 'validation_error': 'Please check your input and try again.', + 'authentication_failed': 'Invalid credentials.', + 'permission_denied': 'You do not have permission to perform this action.', + 'resource_not_found': 'The requested resource was not found.', + 'server_error': 'An error occurred. Please try again later.', + 'bad_request': 'Invalid request. Please check your input.', + 'unauthorized': 'Authentication required.', + 'forbidden': 'Access denied.', + 'not_found': 'Resource not found.', + 'method_not_allowed': 'Method not allowed.', + 'request_timeout': 'Request timed out. Please try again.', + 'conflict': 'Resource conflict. Please try again.', + 'too_many_requests': 'Too many requests. Please try again later.', + 'internal_server_error': 'An error occurred. Please try again later.', + 'service_unavailable': 'Service temporarily unavailable. Please try again later.' +}; + export async function extractErrorMessageFromResponse(r: Response) { let data; try { data = await r.clone().json(); } catch (e) { - if (window.APP_SETTINGS.debug) { - console.error(e); + // Log detailed error internally for debugging + if (window.APP_SETTINGS?.debug) { + console.error('Error parsing response:', e); } - return extractErrorMessage(e) ?? "Error: " + r.status + " / " + r.statusText; + // Return generic message in production to prevent information disclosure + return "An error occurred. Please try again later."; } - return extractErrorMessage(data) ?? "Error: " + r.status + " / " + r.statusText; + const errorMessage = extractErrorMessage(data); + + // Only show detailed errors in debug mode + if (window.APP_SETTINGS?.debug) { + return errorMessage ?? `Error: ${r.status} / ${r.statusText}`; + } + + // Map to safe message or use generic fallback + if (errorMessage && SAFE_ERROR_MESSAGES[errorMessage.toLowerCase()]) { + return SAFE_ERROR_MESSAGES[errorMessage.toLowerCase()]; + } + + // Return generic message for production to prevent information disclosure + return "An error occurred. Please try again later."; } export function unexpectedErrorMessage(e: any): string { - if (typeof e.toString === "function") { - return "Unexpected error occurred. Error: " + e?.toString(); + // Log detailed error internally for debugging + if (window.APP_SETTINGS?.debug) { + console.error('Unexpected error details:', e); } - - return "Unexpected error occurred"; + + // Return generic message in production to prevent information disclosure + return "An unexpected error occurred. Please try again later."; }