-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Fix email enumeration vulnerabilities in password reset and registration flows #5790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix email enumeration vulnerabilities in password reset and registration flows #5790
Conversation
Previously, the password reset functionality exposed whether an email existed in the system by returning different responses for existing vs non-existing accounts. This is a security vulnerability that allows attackers to enumerate valid user emails. This commit makes the following changes: - Always return a success response with a vague message for password reset requests - Remove dependency on paranoid mode for this security feature - Update locale messages to use consistent, non-revealing language - Update tests to reflect the new secure-by-default behavior The new behavior always shows: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." This is a breaking change but improves security by default. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
How do you fix the same problem at registration? I usually recommend rate limiting for these, so even if your response indicates the existence of a user, it is difficult to enumerate a large list. |
That is a good question. I would likely need a different solution, which I have not considered yet. Rate limiting does the trick to stop or make enumeration untenible. It still exposes data unnecessarily, which gets flagged on every pentest, which then has to be dealt with either through explanation or fixing the issue on a per install basis. |
Those pentesters should focus on bigger issues :) I would put such thing maybe as informal on a report and if they don't mention the sign up flow having the same problem, I am not sure what are they doing. |
Yes, they should. I don't disagree, but it has been on multiple reports for multiple companies that I've been involved with over the years. This PR came out of using a new Saas build on Rails using Devise, so I decided to stop wishing someone open a PR and just did it. I'm happy to work on the sign-up flow as well. |
Also, I could put this behind the |
I am not against this change, I just wanted to point out that this doesn't solve the actual problem, just partially mitigates it. |
When paranoid mode is enabled, registration attempts with existing emails now: - Show the same success message as new registrations - Send an "already registered" email to the existing user - Redirect to sign-in page instead of showing validation errors This prevents attackers from discovering which emails have accounts by attempting to register with them. Changes: - Add paranoid mode check to RegistrationsController#create - Create new mailer method and template for "already registered" emails - Update tests to verify the new secure behavior - Fix test expectations for default non-enumerable password reset 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Generate a dummy token when user not found to make timing analysis harder. This ensures similar computational work is performed whether the user exists or not, making it more difficult to determine email existence through response time analysis. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
I have an idea to resolve this during sign up, but I think that would be too big of a change in devise. |
I like that flow. Could it be behind the paranoid flag? I did something like that on my commits, but changed it in the paranoid flag. |
Summary
Problem
Devise had two email enumeration vulnerabilities:
Both vulnerabilities allow attackers to enumerate valid user emails.
Solution
Password Reset (Breaking Change - Secure by Default)
Registration (Opt-in via Paranoid Mode)
Devise.paranoid = true
, duplicate registration attempts:Breaking Changes
send_reset_password_instructions
no longer returns errors for non-existent emails by defaultChanges Made
send_reset_password_instructions
inlib/devise/models/recoverable.rb
PasswordsController#create
to always show successRegistrationsController#create
Test Plan
Security Impact
This significantly improves security by preventing email enumeration attacks, a common vulnerability used in reconnaissance phases of attacks.
🤖 Generated with Claude Code