You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The email provider handles resend in pre_process_authentication(), but Two_Factor_Core::process_provider() applies is_user_rate_limited() only afterward. As a result, resend requests are not subject to the same retry-delay gate as verification attempts.
Why this matters
For email-based 2FA, a user who has already hit the plugin's retry delay after invalid verification attempts can still trigger Resend Code. Each resend generates a fresh token via generate_and_email_token(), replacing the one that an attacker may have been trying to guess. This effectively resets the brute-force window while the rate limit is still active — the delay blocks verification attempts but not the token rotation that undermines it.
This is an inference from current source, not a confirmed exploit. It looks like an auth-flow / abuse-hardening gap rather than a full auth bypass.
Verified code path
Two_Factor_Core::process_provider() calls $provider->pre_process_authentication( $user ) before it checks is_user_rate_limited( $user ).
Two_Factor_Email::pre_process_authentication() resends whenever two-factor-email-code-resend is present.
The rate-limit check runs only later in process_provider(), so it does not gate the resend branch.
Current behavior from source
Resend is handled as provider pre-processing.
Rate limiting is applied only to the subsequent verification path.
I did not find a dedicated resend throttle in the email provider path.
Potential impact
Repeated resend requests can generate additional email traffic even when verification attempts are temporarily delayed.
Integrators embedding the provider UI inside another challenge flow may see resend behavior that does not match the plugin's normal retry messaging.
Suggested fix
Either:
Move the rate-limit check ahead of provider pre-processing for resend-capable flows, or
add a dedicated resend throttle in Two_Factor_Email::pre_process_authentication().
Related context
This seems adjacent to the broader throttling discussion in Throttle second factor attempts #477, but I could not find a report specifically about the email resend path surviving the existing retry-delay check.
Summary
The email provider handles resend in
pre_process_authentication(), butTwo_Factor_Core::process_provider()appliesis_user_rate_limited()only afterward. As a result, resend requests are not subject to the same retry-delay gate as verification attempts.Why this matters
For email-based 2FA, a user who has already hit the plugin's retry delay after invalid verification attempts can still trigger Resend Code. Each resend generates a fresh token via
generate_and_email_token(), replacing the one that an attacker may have been trying to guess. This effectively resets the brute-force window while the rate limit is still active — the delay blocks verification attempts but not the token rotation that undermines it.This is an inference from current source, not a confirmed exploit. It looks like an auth-flow / abuse-hardening gap rather than a full auth bypass.
Verified code path
Two_Factor_Core::process_provider()calls$provider->pre_process_authentication( $user )before it checksis_user_rate_limited( $user ).Two_Factor_Email::pre_process_authentication()resends whenevertwo-factor-email-code-resendis present.process_provider(), so it does not gate the resend branch.Current behavior from source
Potential impact
Suggested fix
Either:
Two_Factor_Email::pre_process_authentication().Related context