fix: enhance password reset flow to prevent username enumeration
This commit is contained in:
parent
db4afbd021
commit
f00c4b7738
2 changed files with 18 additions and 26 deletions
|
|
@ -1127,24 +1127,24 @@ def sign_up(email: str, full_name: str, redirect_to: str) -> tuple[int, str]:
|
|||
@frappe.whitelist(allow_guest=True, methods=["POST"])
|
||||
@rate_limit(limit=get_password_reset_limit, seconds=60 * 60)
|
||||
def reset_password(user: str) -> str:
|
||||
# Always return the same generic response regardless of whether the user
|
||||
# exists, is disabled, or is restricted. This prevents username enumeration
|
||||
# via different messages or HTTP status codes (CWE-204).
|
||||
|
||||
try:
|
||||
user: User = frappe.get_doc("User", user)
|
||||
if user.name == "Administrator":
|
||||
return "not allowed"
|
||||
if not user.enabled:
|
||||
return "disabled"
|
||||
|
||||
user.validate_reset_password()
|
||||
user.reset_password(send_email=True)
|
||||
|
||||
return frappe.msgprint(
|
||||
msg=_("Password reset instructions have been sent to {}'s email").format(user.full_name),
|
||||
title=_("Password Email Sent"),
|
||||
)
|
||||
user_doc: User = frappe.get_doc("User", user)
|
||||
if user_doc.name != "Administrator" and user_doc.enabled:
|
||||
user_doc.validate_reset_password()
|
||||
user_doc.reset_password(send_email=True)
|
||||
# For Administrator or disabled users: silently skip — same response below
|
||||
except frappe.DoesNotExistError:
|
||||
frappe.local.response["http_status_code"] = 404
|
||||
frappe.clear_messages()
|
||||
return "not found"
|
||||
# Do not reveal whether the account exists — fall through to generic response
|
||||
|
||||
return frappe.msgprint(
|
||||
msg=_("If an account with this email exists, password reset instructions have been sent."),
|
||||
title=_("Password Reset"),
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
|
|||
|
|
@ -247,17 +247,9 @@ login.login_handlers = (function () {
|
|||
window.location.href = data.home_page;
|
||||
}
|
||||
} else if (window.location.hash === '#forgot') {
|
||||
if (data.message === 'not found') {
|
||||
login.set_status({{ _("Not a valid user") | tojson }}, 'red');
|
||||
} else if (data.message == 'not allowed') {
|
||||
login.set_status({{ _("Not Allowed") | tojson }}, 'red');
|
||||
} else if (data.message == 'disabled') {
|
||||
login.set_status({{ _("Not Allowed: Disabled User") | tojson }}, 'red');
|
||||
} else {
|
||||
login.set_status({{ _("Instructions Emailed") | tojson }}, 'green');
|
||||
}
|
||||
|
||||
|
||||
// Always show the same message regardless of whether the account
|
||||
// exists or not, to prevent username enumeration (CWE-204).
|
||||
login.set_status({{ _("Instructions Emailed") | tojson }}, 'green');
|
||||
} else if (window.location.hash === '#signup') {
|
||||
if (cint(data.message[0]) == 0) {
|
||||
login.set_status(data.message[1], 'red');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue