Skip to content

Conversation

@callmesangio
Copy link
Contributor

Previously, the password confirmation validation added by has_secure_password was skipped if the password string was a sequence of whitespace characters, regardless of the string provided as confirmation, which was ignored with no error messages.

This change fixes that behavior, so that the confirmation validation runs consistently, independently of the password string content.

Fixes #55225

Motivation / Background

This Pull Request has been created because it fixes a bug in has_secure_password validations.

Detail

This Pull Request changes how the password confirmation validation added by default by has_secure_password works.

Additional information

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

end

validates_confirmation_of attribute, allow_blank: true
validates_confirmation_of attribute, allow_nil: true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change assumes that, given the current implementation of the writer method password=, the corresponding reader method password can only actually return nil or a string that is not empty? (whitespace-only or not). Therefore, by skipping the confirmation validation only when password is nil, we get to validate every non-empty string, which is what we want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the condition of a "blank" value here related to the fact that a <form> element submitted with an empty <input type="password"> will be transformed into an empty "" by a controller's params helper? When would an empty <input> result in a nil value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my knowledge, an empty form <input> should not result in a nil value, but nonetheless, nil as a password value (e.g. assigned by other means) is explicitly supported, and has the effect of setting password_digest to nil as well, see https://github.com/rails/rails/blob/main/activemodel/lib/active_model/secure_password.rb#L187. We want to skip confirmation in that case alone.
Plus, I tried to remove the allow_ condition altogether, but that resulted in test failures.
Let me know if I answered your question!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to me. If there was a confirmation field in the form, you'll get "", if the field is being changed from another context, it just won't be there at all (nil).

end

test "create a new user with validation, a spaces only password, and an incorrect password confirmation" do
@user.password = " " * 72
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason for 72 here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatheusRich No technical reason, just consistency: I followed what looked like a convention applied by other test methods of the class.

But yeah, as @simi says, 72 (bytes, not characters) is the limit beyond which bcrypt implementations usually truncate the plaintext.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. I was just wondering if it meant something relevant for this test. I wonder if it makes sense to just use a single space, as that seems to be enough for this test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatheusRich I made the change to have a single space string, and updated the commit accordingly, see https://github.com/rails/rails/compare/8de663fde4e813aef4c7593a55c216818bd81a6c..20e28b900dad008784c36f08742b426c0e7b6ceb

@callmesangio callmesangio force-pushed the fix-gh-55225 branch 2 times, most recently from 8de663f to 20e28b9 Compare July 14, 2025 15:16
@callmesangio callmesangio requested a review from MatheusRich July 14, 2025 15:31
@MatheusRich MatheusRich added the ready PRs ready to merge label Jul 14, 2025
@MatheusRich
Copy link
Contributor

I'm unsure if this is considered a bugfix, so IDK if we need a changelog entry for it. I'll let someone else chime in.

Previously, the password confirmation validation added by
`has_secure_password` was skipped if the password string was a sequence
of whitespace characters, regardless of the string provided as
confirmation, which was ignored with no error messages.

This change fixes that behavior, so that the confirmation validation
runs consistently, independently of the password string content.

Fixes rails#55225
@callmesangio
Copy link
Contributor Author

Hello there 👋🏻
Is there anything I can do to push this forward?
Thanks!

@byroot
Copy link
Member

byroot commented Jul 22, 2025

I'm unsure if this is considered a bugfix,

I'd say so. But it's easier to add the changelog during backport anyways.

@byroot byroot merged commit 1351d54 into rails:main Jul 22, 2025
3 checks passed
@callmesangio callmesangio deleted the fix-gh-55225 branch July 22, 2025 15:21
byroot added a commit that referenced this pull request Jul 22, 2025
`has_secure_password`: fix password validation.
byroot added a commit that referenced this pull request Jul 22, 2025
`has_secure_password`: fix password validation.
@byroot
Copy link
Member

byroot commented Jul 22, 2025

Backported to 8-0-stable and 7-2-stable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

activemodel ready PRs ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[has_secure_password] Password confirmation validation skipped if password is whitespace-only

5 participants