Version 2.0.0

July 8, 2026

Breaking (proxied sites only): client IP detection now respects Craft's trusted-proxy configuration instead of unconditionally trusting forwarding headers. If your site runs behind Cloudflare, a load balancer, or another reverse proxy, configure trustedHosts/ipHeaders in config/general.php (see proxy configuration guidance) — otherwise all login attempts are attributed to the proxy's IP. Sites with direct connections are unaffected.

Security

  • Fixed IP spoofing in client IP detection. ProtectionService::getClientIp() previously trusted the CF-Connecting-IP, X-Forwarded-For, and X-Real-IP request headers unconditionally and used the left-most value, which is client-controlled. This let an attacker rotate a header to bypass blocking entirely, bypass the IP whitelist, or spoof a victim's IP to lock a legitimate user out of the Control Panel. IP detection now delegates to Craft's Request::getUserIP(), which honors forwarded headers only from proxies you've marked as trusted via trustedHosts/ipHeaders in config/general.php. Sites behind Cloudflare or a reverse proxy should review the proxy configuration guidance.
  • Fixed a front-end login block bypass. Front-end enforcement only recognized a login when the action was passed as a POST body param, so a blocked IP could keep attempting logins by targeting the /actions/users/login path or query-string form instead. Enforcement now inspects the resolved action, which is invariant across all invocation forms.
  • Bounded database writes from blocked IPs. A blocked IP that kept hitting the login endpoint previously caused one login-attempt row (plus a re-save of the block row) to be written per request, which an attacker could use to flood the database. Writes for an already-blocked IP are now throttled to at most once per 60 seconds; the 403 block is still returned on every request.

Changed

  • The block response for blocked IPs is now emitted through Craft's response pipeline (via Craft::$app->end()) instead of raw echo/exit, so framework content-type/charset handling, security-header events, and end-of-request cleanup all apply. The response contract (JSON {success, message, error} for AJAX, styled HTML otherwise, X-Login-Lockdown header, HTTP 403) is unchanged.
  • Removed leftover debug logging from the Pushover test action and notification service.

Version 1.0.5

June 9, 2026

Changed

  • Bumped minimum Craft CMS to ^5.9.18 (was ^5.8.0) so consumers no longer install Craft versions affected by GHSA-gj2p-p9m4-c8gw, GHSA-qrgm-p9w5-rrfw, and GHSA-33m5-hqp9-97pw, all patched in Craft 5.9.18
  • Stopped committing composer.lock — distributed plugins shouldn't ship lock files, since consumers resolve dependencies against their own. This also clears noise from Dependabot scans of transitive dependencies that don't actually affect consumers
  • Added a .github/dependabot.yml restricting Composer scans to direct dependencies and only opening PRs when a new version falls outside the existing constraint, so future Dependabot activity reflects real security updates rather than lockfile churn

Version 1.0.4

March 24, 2026

Fixed

  • Non-admin users with plugin access can now view the blocked IPs page without getting a 403 error
  • CP nav item now hidden for users without plugin access permission

Version 1.0.3

February 4, 2026

Fixed

  • Login attempts from already-blocked IPs are now recorded and reset the lockout timer

Version 1.0.2

February 2, 2026

Fixed

  • Corrected GitHub repository URLs in composer.json documentation and support links

Version 1.0.1

February 2, 2026

Added

  • Block expiration time now included in email and Pushover notification messages

Version 1.0.0

February 2, 2026

Added

  • Brute force protection for Craft CMS control panel login
  • Brute force protection for front-end login forms
  • Configurable failed attempt threshold and time window
  • Configurable lockout duration
  • IP whitelist to exclude trusted addresses from blocking
  • Email notifications when IPs are blocked
  • Pushover notifications when IPs are blocked
  • Control panel interface for viewing and managing blocked IPs
  • CLI commands for managing blocked IPs (login-lockdown/block/list, add, remove, check)
  • CLI command for cleaning up old records (login-lockdown/cleanup)
  • Proxy-aware IP detection (Cloudflare, X-Forwarded-For, X-Real-IP)
  • Environment variable support for all settings using $ENV_VAR syntax