{"id":346001,"date":"2026-08-21T05:35:17","date_gmt":"2026-08-21T05:35:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/yard-warden\/"},"modified":"2026-08-21T13:54:54","modified_gmt":"2026-08-21T13:54:54","slug":"yard-warden","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/yard-warden\/","author":23069227,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.5","stable_tag":"1.0.5","tested":"7.0.4","requires":"6.3","requires_php":"7.4","requires_plugins":null,"header_name":"Yard | Warden","header_author":"Yard | Digital Agency","header_description":"Enhanced password and login security for WordPress.","assets_banners_color":"c9ebea","last_updated":"2026-08-21 13:54:54","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/www.yard.nl","rating":0,"author_block_rating":0,"active_installs":0,"downloads":37,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.3":{"tag":"1.0.3","author":"yarddigitalagency","date":"2026-08-21 05:34:52"},"1.0.4":{"tag":"1.0.4","author":"yarddigitalagency","date":"2026-08-21 13:05:52"},"1.0.5":{"tag":"1.0.5","author":"yarddigitalagency","date":"2026-08-21 13:54:54"}},"upgrade_notice":{"1.0.5":"<p>Licensing and packaging metadata only, no action required.<\/p>","1.0.4":"<p>Bugfix for Composer-based installs, no action required.<\/p>","1.0.3":"<p>Login attempt counters and active lockouts are reset on upgrade. If you use the disable_welcome_email query flag, rename it to yard_warden_disable_welcome_email.<\/p>","1.0.2":"<p>Text domain change only, no action required.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3658261,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3658261,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3658261,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3658261,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.3","1.0.4","1.0.5"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[2439,602,441,1930,600],"plugin_category":[38,51,54],"plugin_contributors":[230332],"plugin_business_model":[],"class_list":["post-346001","plugin","type-plugin","status-publish","hentry","plugin_tags-brute-force","plugin_tags-login","plugin_tags-multisite","plugin_tags-password","plugin_tags-security","plugin_category-authentication","plugin_category-multisite","plugin_category-security-and-spam-protection","plugin_contributors-yarddigitalagency","plugin_committers-yarddigitalagency"],"banners":{"banner":"https:\/\/ps.w.org\/yard-warden\/assets\/banner-772x250.png?rev=3658261","banner_2x":"https:\/\/ps.w.org\/yard-warden\/assets\/banner-1544x500.png?rev=3658261","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/yard-warden\/assets\/icon-128x128.png?rev=3658261","icon_2x":"https:\/\/ps.w.org\/yard-warden\/assets\/icon-256x256.png?rev=3658261","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Yard Warden hardens core WordPress password and login flows:<\/p>\n\n<ul>\n<li><strong>Password strength<\/strong> via <a href=\"https:\/\/github.com\/bjeavons\/zxcvbn-php\">zxcvbn-php<\/a>. Scores passwords 0-4 (default 4) based on real guessability, not arbitrary character-class rules. User inputs (login, email, display name) are fed to zxcvbn so passwords containing them score lower.<\/li>\n<li><strong>Minimum length<\/strong> enforcement (default 16) on top of the zxcvbn score.<\/li>\n<li><strong>Generic login errors<\/strong> to prevent username enumeration on the wp-login form. Always on, no toggle. Only applies to authentication failures; password-reset and profile-update validation errors remain verbose so users can correct their input.<\/li>\n<li><strong>Safer multisite onboarding.<\/strong> Auto-activates new signups server-side so no activation link is emailed and the wp-activate.php landing page (which would print username + plaintext password) is never reached. The welcome email is rewritten to contain a one-time password-reset link instead of a generated password.<\/li>\n<li><strong>Login limiting<\/strong> via transient-based counters across three dimensions (IP+Username, IP, Username). Locks out brute-force attempts. Admin can clear all counters via Settings &gt; Yard Warden.<\/li>\n<\/ul>\n\n<h4>Filters<\/h4>\n\n<ul>\n<li><code>yard::warden\/password\/min-length<\/code> (default <code>16<\/code>) - Minimum character count.<\/li>\n<li><code>yard::warden\/password\/min-score<\/code> (default <code>4<\/code>) - Minimum zxcvbn score (0-4).<\/li>\n<li><code>yard::warden\/login\/generic-error<\/code> (default <code>Invalid credentials.<\/code>) - Replacement login error message.<\/li>\n<li><code>yard::warden\/login\/leaky-error-codes<\/code> (default <code>['invalid_username', 'invalid_email', 'incorrect_password']<\/code>) - WP_Error codes to rewrite.<\/li>\n<li><code>yard::warden\/onboarding\/welcome-subject<\/code> (default <code>Welcome to &lt;site&gt;!<\/code>) - Multisite welcome email subject.<\/li>\n<li><code>yard::warden\/onboarding\/welcome-body<\/code> (default reset-link body) - Full welcome email body. Receives <code>$user<\/code>, <code>$resetUrl<\/code>, original body.<\/li>\n<li><code>yard::warden\/limit-login\/enabled<\/code> (default <code>true<\/code>) - Set to <code>false<\/code> to disable login limiting entirely.<\/li>\n<li><code>yard::warden\/limit-login\/client-ip<\/code> (default <code>REMOTE_ADDR<\/code>) - Override IP detection (e.g. for reverse proxies).<\/li>\n<li><code>yard::warden\/limit-login\/error-message<\/code> (default <code>Too many failed login attempts...<\/code>) - Lockout error shown to the user.<\/li>\n<li><code>yard::warden\/limit-login\/skip-error-codes<\/code> (default <code>['expired_session']<\/code>) - WP_Error codes that do not count as failed attempts.<\/li>\n<li><code>yard::warden\/limit-login\/threshold\/{dimension}<\/code> (default <code>5<\/code> \/ <code>50<\/code> \/ <code>3<\/code>) - Attempts before lockout per dimension (<code>ip_user<\/code> \/ <code>ip<\/code> \/ <code>username<\/code>).<\/li>\n<li><code>yard::warden\/limit-login\/window\/{dimension}<\/code> (default <code>300<\/code> \/ <code>3600<\/code> \/ <code>1500<\/code>) - Counting window in seconds per dimension.<\/li>\n<li><code>yard::warden\/limit-login\/lockout\/{dimension}<\/code> (default <code>300<\/code> \/ <code>3600<\/code> \/ <code>1500<\/code>) - Lockout duration in seconds per dimension.<\/li>\n<\/ul>\n\n<h4>Policy override example<\/h4>\n\n<pre><code>add_filter('yard::warden\/password\/min-score', function (int $score) {\n    return max($score, 4);\n});\n<\/code><\/pre>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin files to <code>\/wp-content\/plugins\/yard-warden<\/code>, or install through the Plugins screen directly.<\/li>\n<li>Activate the plugin through the \"Plugins\" screen in WordPress.<\/li>\n<li>Configure login-limit thresholds via Settings &gt; Yard Warden, or override any default via the filters above.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20this%20add%20password%20expiry%20or%20forced%20rotation%3F\"><h3>Does this add password expiry or forced rotation?<\/h3><\/dt>\n<dd><p>No. Forced password rotation is not implemented; it pushes users toward weaker, predictable passwords rather than improving security.<\/p><\/dd>\n<dt id=\"can%20i%20disable%20login%20limiting%3F\"><h3>Can I disable login limiting?<\/h3><\/dt>\n<dd><p>Yes, via the <code>yard::warden\/limit-login\/enabled<\/code> filter.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.5<\/h4>\n\n<ul>\n<li>Source code published on GitHub and the package registered on Packagist.<\/li>\n<li>Added the EUPL-1.2 licence text and declared it in composer.json.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Fixed a fatal error when the plugin is installed via Composer, where dependencies are autoloaded by the project instead of the plugin.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Minimum WordPress version raised to 6.3.<\/li>\n<li>Bundled Dutch translations removed; translations are now served through translate.wordpress.org.<\/li>\n<li>WP_Error codes prefixed with yard_warden_ to avoid collisions with other plugins.<\/li>\n<li>Login-limit transient keys prefixed with yard_warden_ll_.<\/li>\n<li>Welcome-email opt-out query flag renamed to yard_warden_disable_welcome_email.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Text domain adjusted to yard-warden.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Enhanced password and login security for WordPress.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/346001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=346001"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/yarddigitalagency"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=346001"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=346001"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=346001"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=346001"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=346001"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=346001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}