Surfaced during P8a (#3814) E20 whitelist audit. Pre-existing, out of P8a scope β filing for tracking.
Symptom
A logged-in, email-verified user can change their email to an arbitrary address (e.g. a victim's) via PUT /api/users and keep emailVerified: true β it is not reset on email change.
Root cause
email IS in config.whitelists.users.update (users.development.config.js), so removeSensitive lets a new email through the self-update path.
- The update path does not reset
emailVerified when email changes (emailVerified isn't in the update whitelist, so removeSensitive leaves the existing true untouched).
Impact
OAuth account linking (linkProviderByEmail) filters { email, emailVerified: true }. An attacker sets their account's email to a victim's address (kept verified) β a later OAuth sign-in for that address is linked/annexed to the attacker's account (or vice-versa, depending on flow). Identity-confusion / account-takeover surface.
Suggested fix (pick one)
- On email change via any user-update path, set
emailVerified: false and re-trigger the verification flow (don't trust the new address until proven).
- Remove
email from the self-update whitelist entirely; require a dedicated verify-email-change flow (request β confirm via token to the new address).
Option 1 is the smaller change; option 2 is the more robust contract.
Also
Candidate for an ERRORS.md entry (symptom / root cause / fix) once resolved.
Refs #3814 #3808.
Surfaced during P8a (#3814) E20 whitelist audit. Pre-existing, out of P8a scope β filing for tracking.
Symptom
A logged-in, email-verified user can change their email to an arbitrary address (e.g. a victim's) via
PUT /api/usersand keepemailVerified: trueβ it is not reset on email change.Root cause
emailIS inconfig.whitelists.users.update(users.development.config.js), soremoveSensitivelets a new email through the self-update path.emailVerifiedwhenemailchanges (emailVerifiedisn't in theupdatewhitelist, soremoveSensitiveleaves the existingtrueuntouched).Impact
OAuth account linking (
linkProviderByEmail) filters{ email, emailVerified: true }. An attacker sets their account's email to a victim's address (kept verified) β a later OAuth sign-in for that address is linked/annexed to the attacker's account (or vice-versa, depending on flow). Identity-confusion / account-takeover surface.Suggested fix (pick one)
emailVerified: falseand re-trigger the verification flow (don't trust the new address until proven).emailfrom the self-update whitelist entirely; require a dedicated verify-email-change flow (request β confirm via token to the new address).Option 1 is the smaller change; option 2 is the more robust contract.
Also
Candidate for an
ERRORS.mdentry (symptom / root cause / fix) once resolved.Refs #3814 #3808.