From a5252ee0d1ff95ac98bf083114df6d3ff37180db Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 19 Jan 2026 11:44:13 -0800 Subject: [PATCH] security: sanitize error messages to prevent info disclosure Replace detailed error messages with generic ones to prevent leaking internal system information to users. Actual errors are logged for debugging. - OAuth errors: "Authentication failed" instead of err.Error() - Session errors: "Session error" instead of err.Error() - JSON decode errors: "Invalid request body" instead of decode error - Logout errors: "Logout failed" instead of err.Error() Note: Validation errors (like "Invalid date format") are kept as they help users understand what needs to be fixed. Co-Authored-By: Claude Opus 4.5 --- backend/controllers/add_task.go | 3 ++- backend/controllers/app_handlers.go | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/controllers/add_task.go b/backend/controllers/add_task.go index b33eaddd..60ff42c0 100644 --- a/backend/controllers/add_task.go +++ b/backend/controllers/add_task.go @@ -27,7 +27,8 @@ func AddTaskHandler(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { var requestBody models.AddTaskRequestBody if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil { - http.Error(w, fmt.Sprintf("error decoding request body: %v", err), http.StatusBadRequest) + utils.Logger.Warnf("Failed to decode add task request: %v", err) + http.Error(w, "Invalid request body", http.StatusBadRequest) return } defer r.Body.Close() diff --git a/backend/controllers/app_handlers.go b/backend/controllers/app_handlers.go index 29ba4300..ac7f0c56 100644 --- a/backend/controllers/app_handlers.go +++ b/backend/controllers/app_handlers.go @@ -48,21 +48,24 @@ func (a *App) OAuthCallbackHandler(w http.ResponseWriter, r *http.Request) { t, err := a.Config.Exchange(context.Background(), code) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + utils.Logger.Errorf("OAuth token exchange failed: %v", err) + http.Error(w, "Authentication failed", http.StatusBadRequest) return } client := a.Config.Client(context.Background(), t) resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo") if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + utils.Logger.Errorf("Failed to fetch user info from Google: %v", err) + http.Error(w, "Authentication failed", http.StatusBadRequest) return } defer resp.Body.Close() var userInfo map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + utils.Logger.Errorf("Failed to decode user info: %v", err) + http.Error(w, "Authentication failed", http.StatusInternalServerError) return } @@ -80,7 +83,8 @@ func (a *App) OAuthCallbackHandler(w http.ResponseWriter, r *http.Request) { session, _ := a.SessionStore.Get(r, "session-name") session.Values["user"] = userInfo if err := session.Save(r, w); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + utils.Logger.Errorf("Failed to save session: %v", err) + http.Error(w, "Session error", http.StatusInternalServerError) return } @@ -137,7 +141,8 @@ func (a *App) LogoutHandler(w http.ResponseWriter, r *http.Request) { session, _ := a.SessionStore.Get(r, "session-name") session.Options.MaxAge = -1 if err := session.Save(r, w); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + utils.Logger.Errorf("Failed to clear session on logout: %v", err) + http.Error(w, "Logout failed", http.StatusInternalServerError) return }