Lost Password Hardening
Hardens the WordPress "Lost Password" page against bots and account enumeration — adds rate limiting, a honeypot field, and generic error responses.
by John Mark Bondad · github.com/john-mark-bondad/lostpassword-hardening · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/john-mark-bondad/lostpassword-hardening/archive/refs/heads/master.zipA lightweight WordPress plugin that hardens the default wp-login.php?action=lostpassword page against bots and brute-force / account-enumeration attacks — without requiring a full security suite.
Why
The default WordPress "Lost Password" page has a few weaknesses out of the box:
- It reveals whether a username or email exists on the site (account enumeration).
- It has no rate limiting, so bots can submit the form thousands of times per minute.
- It has no bot filtering (CAPTCHA, honeypot, etc.).
- Failed/suspicious attempts aren't logged anywhere.
This plugin patches those gaps using WordPress core hooks only — no external dependencies, no API keys required.
Features
- Rate limiting — throttles repeated password reset attempts per IP address (default: 3 attempts per 15 minutes).
- Honeypot field — adds an invisible field to the form that only bots fill in; real visitors never see it.
- Generic responses — always shows the same message ("If an account exists...") regardless of whether the username/email is valid, so attackers can't use the form to discover real accounts.
- Request logging — logs reset requests, rate-limit hits, and honeypot triggers (with IP and timestamp) to your PHP error log for monitoring.
- Shorter reset link lifetime — reduces the password reset link validity window from the WordPress default of 24 hours down to 12 hours.
- Fail-safe error handling — every custom check is wrapped in try/catch, so a failure in this plugin logs an error instead of breaking the password reset flow for legitimate users.
Installation
Option A — Regular plugin (recommended for most sites)
- Download the latest release or clone this repo.
- Zip the
lostpassword-hardeningfolder (or use the provided.zip). - In wp-admin, go to Plugins → Add New → Upload Plugin and upload the zip.
- Click Activate.
Option B — Must-use plugin (always-on, can't be accidentally deactivated)
- Copy just
lostpassword-hardening.php(not the folder) intowp-content/mu-plugins/. - Create the
mu-pluginsfolder if it doesn't already exist. - That's it — mu-plugins load automatically, no activation step needed.
Note: mu-plugins don't support subfolders being auto-loaded, so this file must sit loose directly inside
mu-plugins/, not inside its own directory.
Verifying it works
- Submit the lost password form more than 3 times in a row from the same IP — you should see "Too many password reset attempts" on the 4th try.
- Check your PHP error log (or
wp-content/debug.logifWP_DEBUG_LOGis enabled inwp-config.php) for entries prefixed with[LostPassword].
Configuration
All settings are constants inside lostpassword-hardening.php:
| Setting | Location | Default |
|---|---|---|
| Max attempts before throttling | Section 1 ($max_attempts) |
3 |
| Throttle window | Section 1 ($window_seconds) |
15 minutes |
| Reset link expiration | Section 5 (password_reset_expiration filter) |
12 hours |
Edit these values directly in the file to adjust thresholds.
Recommended additional layers
This plugin covers the application-level gaps in the lost password flow. For a fuller security posture, consider pairing it with:
- A WAF or IP-level rate limiter (Cloudflare, Wordfence, Sucuri) in front of
wp-login.php. - CAPTCHA (reCAPTCHA v3 / hCaptcha) on the login and lost-password forms.
- Two-factor authentication for all user accounts.
- Disabling XML-RPC if you don't need it.
License
GPL-2.0-or-later — see LICENSE or https://www.gnu.org/licenses/gpl-2.0.html
Author
John Mark Bondad GitHub