Skip to content

Fix race condition vulnerability, by ensuring the unconfirmed_email is always saved#5784

Open
grantcox wants to merge 4 commits intoheartcombo:mainfrom
grantcox:email-confirmation-race-condition-vulnfix
Open

Fix race condition vulnerability, by ensuring the unconfirmed_email is always saved#5784
grantcox wants to merge 4 commits intoheartcombo:mainfrom
grantcox:email-confirmation-race-condition-vulnfix

Conversation

@grantcox
Copy link

@grantcox grantcox commented Jul 7, 2025

Fixes #5783

Copy link

@runephilosof-abtion runephilosof-abtion left a comment

Choose a reason for hiding this comment

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

Another way to solve this, would be to use transactions and locking for update.
However, that might be a problem for some database backends?
Anyway, transactions have not been used anywhere else in Devise and the approach in this PR works.

@grantcox grantcox force-pushed the email-confirmation-race-condition-vulnfix branch from cfa56a4 to 502ed42 Compare August 7, 2025 18:27
@grantcox
Copy link
Author

grantcox commented Aug 7, 2025

Thank you for the feedback @runephilosof-abtion , your changes were very helpful and I've merged them all now

grantcox and others added 2 commits February 4, 2026 10:07
…s always saved even if the submitted value is the same as the in-memory model's state
Co-authored-by: Rune Philosof <57357936+runephilosof-abtion@users.noreply.github.com>
It appears Mongoid differs from AR in that even if you're calling
`will_change!` on an attribute to "force" it to see (and persist)
changes, and it gets set to `changed_attributes` so it knows it's
technically "changed", the model's `changes` which are based on
`attribute_changed?` don't include the field because it didn't actually
"change" from its original value, so it doesn't get persisted by
Mongoid.

This was causing the new test for the confirmable race condition issue
to fail, because `will_change!` wasn't forcing the "change" to be
persisted in Mongoid.

This is a workaround for it, by setting `changed_attributes` directly to
`nil` (could be any value like `__devise-force-change__`) it makes
Mongoid see the changes and persist them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Confirmable "change email" vulnerability - race condition permits user to confirm email address they have no access to

3 participants