From 824b28897ea8e3fcd88436150cd0085ac92d37fc Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Thu, 16 Apr 2026 20:53:03 +0200 Subject: [PATCH] fix: don't show success on validation error in forgot-password forms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The catch-all error handler (for anti-email-enumeration) was also swallowing 422 validation errors, making it appear that a reset email was sent even for empty or invalid input. Now 422 responses are excluded from the catch — the user stays on the form so the field-level validation messages remain visible. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/app/src/pages/forgot-password.vue | 15 ++++++++++++--- apps/portal/src/pages/wachtwoord-vergeten.vue | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/app/src/pages/forgot-password.vue b/apps/app/src/pages/forgot-password.vue index 1bef2da0..7894d2f0 100644 --- a/apps/app/src/pages/forgot-password.vue +++ b/apps/app/src/pages/forgot-password.vue @@ -38,13 +38,22 @@ async function onSubmit(): Promise { email: email.value.trim(), app: 'app', }) + done.value = true } - catch { - // Always show generic success (no email enumeration) + catch (error: unknown) { + const ax = error as { response?: { status?: number } } + + if (ax.response?.status === 422) { + // Validation error — don't show success, let the user fix input + return + } + + // For all other errors (404 user-not-found, network, etc.): + // show generic success to prevent email enumeration + done.value = true } finally { isSubmitting.value = false - done.value = true } } diff --git a/apps/portal/src/pages/wachtwoord-vergeten.vue b/apps/portal/src/pages/wachtwoord-vergeten.vue index 18ae00d2..a38051d1 100644 --- a/apps/portal/src/pages/wachtwoord-vergeten.vue +++ b/apps/portal/src/pages/wachtwoord-vergeten.vue @@ -27,13 +27,22 @@ async function onSubmit(): Promise { isSubmitting.value = true try { await apiClient.post('/auth/forgot-password', { email: email.value.trim(), app: 'portal' }) + done.value = true } - catch { - // Always show generic success (no email enumeration) + catch (error: unknown) { + const ax = error as { response?: { status?: number } } + + if (ax.response?.status === 422) { + // Validation error — don't show success, let the user fix input + return + } + + // For all other errors (404 user-not-found, network, etc.): + // show generic success to prevent email enumeration + done.value = true } finally { isSubmitting.value = false - done.value = true } }