Skip to content

1.10.0

Choose a tag to compare

@nredmond829 nredmond829 released this 21 Sep 13:11
· 22 commits to main since this release
0268dc3

Fix 2FA bypass vulnerabilities

What was broken

  • edit_user/edit_users were allow-listed for 2FA-less accounts, letting them edit any user's profile.
  • admin-ajax.php was fully open pre-2FA instead of scoped to what's actually needed.
  • 2FA requirement is determined by email domain (@829llc.com = SSO, exempt) — a 2FA-less admin could change their own email to instantly escape the requirement.
  • 2FA activated immediately on save with no ownership verification — a stolen password on an account without 2fa could still gain access.

What changed

  • Capability lockdown: edit_user/edit_users removed from the allow-list; self-profile edits now strictly scoped to the user's own ID.
  • Ajax lockdown: admin-ajax.php access for 2FA-less accounts limited to only the actions profile.php needs.
  • Email lock: 2FA-less users can no longer change their own email, enforced at the data layer so it holds across wp-admin, REST, ajax, and CLI.
  • Email-confirmed activation: enabling 2FA now sends a confirmation link that must be clicked (via POST, resistant to link-prefetching scanners) before it actually activates, so a user cannot set up 2fa unless they have access to the account email address. A notice shows while confirmation is pending.

Testing

  • Verified the REST bypass (POST /wp/v2/users/me email change) is blocked.
  • Verified capability/ajax restrictions don't break the legitimate profile/2FA-setup flow.
  • Reviewed for new vulnerabilities in this diff (token binding, confirmation-link security) — fixed a token-binding weakness and hardened the confirmation link against link-prefetching scanners.

No impact on existing accounts

  • SSO (@829llc.com) accounts and non-SSO accounts that already have 2FA enabled are unaffected by any of these changes.

Add 2FA login exceptions for third-party integration accounts

Service accounts that hit the REST API with an application password can't complete a 2FA challenge, so TwoFactor permanently strips them down to read. Needed for the Tourcube integration.

Adds an External Email Users → 2FA Login Exceptions field to the 829 Settings page (same user-search pattern as Credential Login Exceptions), and exempts those users in user_requires_2fa().

Note this removes our enforcement only — the Two-Factor plugin will still challenge an exempted user who already has 2FA set up.