CVE-2026-8760 Overview
CVE-2026-8760 is an authentication bypass vulnerability in the Login with OTP plugin for WordPress, affecting all versions up to and including 1.6. The flaw stems from an incomplete fix for CVE-2024-11178, where the rate-limit and lockout enforcement in otpl_login_action() was placed only inside the OTP-generation branch. The OTP-validation branch never evaluates these controls. Compounding the issue, the generated 6-digit one-time password has no expiration. Unauthenticated attackers can brute-force the 900,000-value OTP space against any account, including administrators, to obtain a valid wp_set_auth_cookie() session and fully compromise the site.
Critical Impact
Unauthenticated attackers can brute-force OTP codes against any WordPress account, including administrators, leading to complete site takeover.
Affected Products
- WordPress Login with OTP plugin versions 1.0 through 1.6
- WordPress sites using the otp-login plugin for authentication
- Any deployment relying on the affected plugin for multi-factor or passwordless login
Discovery Timeline
- 2026-05-27 - CVE-2026-8760 published to NVD
- 2026-05-27 - Last updated in NVD database
Technical Details for CVE-2026-8760
Vulnerability Analysis
The vulnerability resides in the otpl_login_action() handler of the Login with OTP plugin. This function services both OTP generation requests and OTP validation requests through the same entry point. The rate-limit and lockout logic introduced to remediate CVE-2024-11178 was placed only in the generation branch. When a request arrives on the validation branch, the function proceeds directly to OTP comparison without consulting any attempt counter.
The second design flaw amplifies the impact. The plugin generates a 6-digit numeric OTP, producing a key space of 900,000 possible values. The plugin does not assign an expiration timestamp to the generated code, so the same OTP remains valid indefinitely until consumed or replaced.
Together these defects enable an attacker to iterate through the entire OTP space against a target account. A successful match invokes wp_set_auth_cookie(), granting an authenticated session bound to that user. When the target is an administrator, the attacker obtains full control of the WordPress instance, including the ability to install plugins, modify content, and execute arbitrary PHP via the theme or plugin editors.
Root Cause
The root cause is improper restriction of excessive authentication attempts [CWE-307]. The lockout check is conditionally scoped to the OTP-issuance code path, leaving the validation path unprotected. The absence of an expiration window on the OTP removes the natural time-bound that would otherwise limit a brute-force window.
Attack Vector
An unauthenticated remote attacker triggers an OTP for a known username, such as admin, then submits validation requests with sequential or randomized 6-digit codes against the plugin endpoint. Because the validation branch skips the lockout check, the attacker can send requests at high volume from a single source or distributed sources. Once a code matches, the response sets an authenticated session cookie.
The vulnerability mechanism is documented in the WordPress plugin source at lib/otpl-class.php lines 361, 419, 424, and 427. Refer to the Wordfence Vulnerability Report for technical details.
Detection Methods for CVE-2026-8760
Indicators of Compromise
- High volumes of POST requests to the WordPress login endpoint carrying the plugin's OTP validation parameter from a single IP or IP range
- Repeated failed OTP validation responses followed by a successful authentication event from the same source
- New administrator sessions or wp_set_auth_cookie() issuance not correlated with a legitimate OTP delivery event
- Unexpected plugin or theme installations, file modifications, or PHP file uploads following a login event
Detection Strategies
- Monitor web server access logs for rapid sequential requests targeting the otpl_login_action parameter or plugin login URL
- Correlate WordPress authentication events with OTP issuance events; sessions established without a corresponding OTP send are suspicious
- Deploy a Web Application Firewall (WAF) rule to flag more than a small threshold of OTP validation attempts per username per minute
Monitoring Recommendations
- Alert on bursts of HTTP 200 responses to wp-login.php or plugin endpoints preceded by many 4xx responses from the same client
- Track creation of new administrative users and changes to wp_users and wp_usermeta tables
- Forward WordPress audit logs and web server logs to a centralized SIEM for cross-source correlation
How to Mitigate CVE-2026-8760
Immediate Actions Required
- Deactivate and remove the Login with OTP plugin until a patched version is released and verified
- Rotate passwords and invalidate active sessions for all administrator and privileged accounts
- Review WordPress audit logs for unauthorized administrator logins, new user creation, and plugin or theme file changes since the plugin was installed
- Deploy WAF rules that enforce strict rate limiting on the plugin's validation endpoint per source IP and per target username
Patch Information
No vendor patch is listed in the NVD record at the time of publication. All versions up to and including 1.6 are vulnerable. Monitor the WordPress plugin repository and the Wordfence Vulnerability Report for fix availability.
Workarounds
- Replace the plugin with an alternative multi-factor authentication solution that enforces rate limiting and short-lived OTPs on both issuance and validation paths
- Restrict access to wp-login.php and plugin authentication endpoints by IP allowlist where operationally feasible
- Place the WordPress login surface behind an authenticating reverse proxy or HTTP basic authentication layer
- Enforce strong, unique administrator usernames to prevent attackers from targeting predictable accounts such as admin
# Example nginx rate-limit configuration for the WordPress login endpoint
limit_req_zone $binary_remote_addr zone=wp_login:10m rate=5r/m;
location = /wp-login.php {
limit_req zone=wp_login burst=5 nodelay;
limit_req_status 429;
include fastcgi_params;
fastcgi_pass php-fpm;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

