Enhancement: Trap URL now sends X-Robots-Tag: noindex, nofollow HTTP header on every response, ensuring search engines cannot index the honeypot URL even if they reach it
Version 1.7.2
Fix: Replace wp_redirect() with wp_safe_redirect() across all admin form handlers
Fix: Replace is_writable() with wp_is_writable() for WP Filesystem API compliance
Fix: Escape block duration integer via absint() in help tab output to satisfy OutputNotEscaped sniff
Fix: Suppress PrefixAllGlobals sniff in admin view template (template-scoped variables, not true PHP globals)
Update: Tested up to WordPress 6.9
Version 1.7.1
Fix: Removed <Limit GET POST HEAD> wrapper from .htaccess block rules — bots using other HTTP methods (DELETE, PUT, PATCH, etc.) are now blocked at the server level too
Enhancement: Background cron hostname resolution batch size increased from 5 to 25 IPs per run, speeding up hostname population on sites with many blocked bots
Performance: EDHBB_Admin class is now only instantiated on admin requests (is_admin() guard), saving memory on every frontend page load
Cleanup: Plugin uninstall now removes all _transient_edhbb_* and _transient_timeout_edhbb_* entries from the options table for a fully clean uninstall
Version 1.7.0
Critical fix: Database migrations now run on plugin updates, not just on activation. A version-based check on plugins_loaded ensures schema changes (e.g. the hostname column) are applied even after automatic updates.
Critical fix: Removed synchronous gethostbyaddr()/gethostbyname() DNS calls from the frontend trap-hit path. These blocking OS calls could hang PHP workers under a botnet DoS. FCrDNS verification now runs exclusively in the background cron — verified legitimate crawlers are automatically unblocked and whitelisted by the cron job.
Fix: Replaced manual preg_replace()/put_contents() .htaccess rewrite with WordPress’s native insert_with_markers(), which uses LOCK_EX file locking to prevent .htaccess corruption under concurrent requests.
Fix: Added uninstall.php — custom database tables, plugin options, and column-exists cache entries are now fully removed when the plugin is deleted via WP Admin.
Fix: Unblocking an IP from a paginated admin list now returns the user to the same page instead of resetting to page 1.
Version 1.6.0
New: FCrDNS (Forward-Confirmed Reverse DNS) verification on trap hits — verified Googlebot, Bingbot, and other legitimate crawlers are protected from being accidentally blocked. Extensible via the edhbb_trusted_crawler_domains filter hook.
Fix: Plugin deactivation now correctly removes .htaccess block rules, matching the documented behaviour. Previously, blocks persisted at the server level after deactivation.
Fix: Cron scheduling moved into the activation hook — removed a redundant wp_next_scheduled() check that ran on every single page load.
Fix: Force-refresh hostname cache now uses delete_transient() per IP instead of a direct SQL DELETE query, ensuring compatibility with object caches (Redis, Memcached) used by managed WordPress hosts.
Enhancement: Blocked bots admin list is now paginated (50 per page) to prevent browser crashes and PHP out-of-memory errors on sites with large numbers of blocked IPs.
Version 1.5.0
Security: Fixed IP spoofing vulnerability — get_client_ip() now uses only REMOTE_ADDR, ignoring spoofable HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR headers
Security: Fixed trap detection false positives — URL path is now compared strictly rather than using loose strpos matching, preventing query strings from triggering blocks
Performance: Eliminated N+1 database queries during .htaccess generation — whitelist is now fetched once and checked with in_array() instead of a query per blocked IP
Performance: init_filesystem() no longer runs on every frontend page load — filesystem is only initialised when .htaccess write operations are actually needed
Performance: is_ip_whitelisted() and is_bot_blocked() now cache results in transients, with targeted cache invalidation on add/remove
Performance: column_exists() result is now cached in a WordPress option, eliminating repeated INFORMATION_SCHEMA queries
Performance: clean_old_blocked_bots() is now gated by an hourly transient, preventing a DELETE query on every page request
Performance: Removed synchronous DNS lookup on trap hit — bot is blocked immediately and hostname is resolved by the background cron job
Performance: Force-refresh-all-hostnames capped at 50 IPs per run to prevent PHP timeout and memory limit issues on large datasets
Fix: Removed [No PTR Record] from the cron retry query — IPs with no PTR record are no longer retried on every hourly run
Fix: Removed broken traditional_hostname_lookup() fallback which passed a raw IP to a PTR lookup (always returned empty)
Fix: Replaced all ReflectionClass usage with direct EDHBB_DNSLookup::get_hostname_for_blocked_ip() calls
Fix: .htaccess marker patterns now wrapped in preg_quote() for correctness
Fix: Reduced verbose DNS debug logging — routine start/end messages removed; only error and fallback messages remain
Accessibility: Added aria-hidden=”true” to the hidden trap link so screen readers ignore it
Version 1.4.3
New: Advanced DNS lookup system with DNS over HTTPS (DoH) support
New: PTR record resolution for hostname identification of blocked IPs
New: Background hostname resolution via WordPress cron jobs
New: Manual hostname update buttons in admin interface
New: Force refresh all hostnames feature with cache clearing
New: Configurable block duration (days) in Options tab
New: Enhanced admin interface with hostname display in blocked bots table
New: Debug information panel for hostname resolution troubleshooting
New: Support for both IPv4 and IPv6 PTR lookups
Enhancement: Improved blocked bots table with hostname column
Enhancement: Better identification of blocked bots through hostname resolution
Enhancement: Automatic database migration system for hostname column
Enhancement: Fallback DNS resolution methods for better compatibility
Enhancement: DNS query caching for improved performance
Fix: Updated queries to gracefully handle missing columns during migration
Fix: Added backward compatibility for existing installations
Fix: Improved error handling and logging for database migrations
Version 1.4.2
Fixed Internal.LineEndings.Mixed in class-edhbb-blocker.php
Version 1.4.1
Fixed blank admin page
Version 1.4.0
Refactored all class names to use the EDHBB_ prefix to prevent conflicts.
Updated the “Tested up to” WordPress version to 6.8.
Corrected the “Requires PHP” version to 7.4 for consistency.
Version 1.3.0
Bringing up to WordPress coding standards
Version 1.2.3
Added instructions to the “Help” tab for excluding the unique trap URL from caching plugins.
Version 1.2.2
Fix: Block duration is now a configurable setting
Version 1.2.1
Fix: Fixing apache error doc
Version 1.2.0
New: Added custom error page
Version 1.1.2
Fix: Now adding htaccess rule at top of file
Version 1.1.1
Fix: Trigger htaccess rules to have higher priority
Version 1.1.0 – Major Feature Release
New: Server-level IP blocking via .htaccess file management
New: “Options” tab in admin interface for configurable blocking methods
Enhanced: Dual-level blocking system (server + PHP) for maximum effectiveness
Added: Automatic .htaccess file management with unique markers
Added: Smart whitelist filtering for .htaccess rules
Improved: Admin interface with enhanced tabbed navigation
Enhanced: Performance optimization with server-level blocking
Added: Nginx compatibility with PHP-only blocking fallback
Updated: Comprehensive documentation including .htaccess functionality
Added: Better error handling and logging for .htaccess operations
Added: Automatic cleanup of .htaccess rules on deactivation
Version 1.0.4
Adding min PHP + WordPress requirements, tested on WordPress 6.8.2
Version 1.0.3
Updated README and license
Version 1.0.2
Added plugin action links for easier access to settings
Version 1.0.1
Changed author name
Version 1.0.0
Initial plugin release
Core bot detection and blocking functionality
Admin interface for managing whitelisted IPs and blocked bots