{"id":304394,"date":"2026-05-04T05:45:07","date_gmt":"2026-05-04T05:45:07","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/wt-hardening\/"},"modified":"2026-05-04T05:44:57","modified_gmt":"2026-05-04T05:44:57","slug":"wt-hardening","status":"publish","type":"plugin","link":"https:\/\/sv.wordpress.org\/plugins\/wt-hardening\/","author":23487023,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.0.2","stable_tag":"1.0.2","tested":"6.9.4","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"WT Hardening","header_author":"webmasters.team","header_description":"Lightweight WordPress hardening: XML-RPC blocker, user enumeration blocker, hide WP version, login limiter, security headers, strong passwords, event log.","assets_banners_color":"ad2f4a","last_updated":"2026-05-04 05:44:57","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/webmasters.team\/","header_plugin_uri":"https:\/\/webmasters.team\/en\/plugins\/wt-hardening\/","header_author_uri":"https:\/\/webmasters.team","rating":0,"author_block_rating":0,"active_installs":0,"downloads":56,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.2":{"tag":"1.0.2","author":"webmastersteam","date":"2026-05-04 05:44:57"}},"upgrade_notice":{"1.0.2":"<p>Plugin URI fix \u2014 points to the new landing page on webmasters.team. No code or behavior changes.<\/p>","1.0.1":"<p>Compliance update: readme translated to English, escape fixes, safer URL parsing. No data or behavior changes.<\/p>","1.0.0":"<p>First release \u2014 install, activate, modules are enabled with sensible defaults.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3521943,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3521943,"resolution":"256x256","location":"assets","locale":""}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3521943,"resolution":"1544x500","location":"assets","locale":""},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3521943,"resolution":"772x250","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3521943,"resolution":"1","location":"assets","locale":""},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3521943,"resolution":"2","location":"assets","locale":""},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3521943,"resolution":"3","location":"assets","locale":""}},"screenshots":{"1":"Settings panel \u2014 modules rendered as cards with toggles and descriptions.","2":"Login attempt log \u2014 currently blocked IPs plus a list of recent failed attempts.","3":"Event log \u2014 chronology of logins, registrations, user changes, and plugin activations."},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[2439,31093,600,153786,14731],"plugin_category":[54],"plugin_contributors":[261801],"plugin_business_model":[],"class_list":["post-304394","plugin","type-plugin","status-publish","hentry","plugin_tags-brute-force","plugin_tags-hardening","plugin_tags-security","plugin_tags-security-headers","plugin_tags-xmlrpc","plugin_category-security-and-spam-protection","plugin_contributors-webmastersteam","plugin_committers-webmastersteam"],"banners":{"banner":"https:\/\/ps.w.org\/wt-hardening\/assets\/banner-772x250.png?rev=3521943","banner_2x":"https:\/\/ps.w.org\/wt-hardening\/assets\/banner-1544x500.png?rev=3521943","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/wt-hardening\/assets\/icon-128x128.png?rev=3521943","icon_2x":"https:\/\/ps.w.org\/wt-hardening\/assets\/icon-256x256.png?rev=3521943","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/wt-hardening\/assets\/screenshot-1.png?rev=3521943","caption":"Settings panel \u2014 modules rendered as cards with toggles and descriptions."},{"src":"https:\/\/ps.w.org\/wt-hardening\/assets\/screenshot-2.png?rev=3521943","caption":"Login attempt log \u2014 currently blocked IPs plus a list of recent failed attempts."},{"src":"https:\/\/ps.w.org\/wt-hardening\/assets\/screenshot-3.png?rev=3521943","caption":"Event log \u2014 chronology of logins, registrations, user changes, and plugin activations."}],"raw_content":"<!--section=description-->\n<p><strong>WT Hardening<\/strong> is a lightweight, modular security plugin that turns on the most important WordPress hardening measures without modifying your theme, <code>wp-config.php<\/code>, or <code>.htaccess<\/code>. Everything works through WordPress hooks and can be disabled at any moment with a single click.<\/p>\n\n<p>The plugin is <strong>completely free<\/strong>, without a PRO version, without ads, and without sending data to external servers. Built by the <a href=\"https:\/\/webmasters.team\">webmasters.team<\/a> crew for daily WordPress work.<\/p>\n\n<h4>Modules<\/h4>\n\n<ul>\n<li><strong>XML-RPC<\/strong> \u2014 blocks <code>xmlrpc.php<\/code> (403) and filters the XML-RPC methods. Stops brute-force attacks through the most attacked WordPress endpoint.<\/li>\n<li><strong>User enumeration<\/strong> \u2014 hides logins by blocking <code>\/wp\/v2\/users<\/code> in the REST API for unauthenticated users.<\/li>\n<li><strong>Author archive<\/strong> \u2014 redirects <code>\/?author=1<\/code> to the homepage (another enumeration vector).<\/li>\n<li><strong>Hide WP version<\/strong> \u2014 removes the <code>&lt;meta name=\"generator\"&gt;<\/code> tag, <code>?ver=<\/code> query strings from assets, and redundant meta tags (wlwmanifest, rsd, shortlink).<\/li>\n<li><strong>X-Pingback<\/strong> \u2014 removes the <code>X-Pingback<\/code> HTTP header from all responses.<\/li>\n<li><strong>Login errors<\/strong> \u2014 replaces the specific \"wrong login \/ wrong password\" messages with a single generic text (does not reveal whether a login exists).<\/li>\n<li><strong>Login limiter<\/strong> \u2014 blocks an IP for X minutes after N failed attempts. Data lives in a dedicated table (not <code>wp_options<\/code>), with hourly cleanup of old entries.<\/li>\n<li><strong>File editor<\/strong> \u2014 sets <code>DISALLOW_FILE_EDIT<\/code>, hiding the theme and plugin editor in the admin (an attacker who compromises an account cannot inject a backdoor through the browser).<\/li>\n<li><strong>Password policy<\/strong> \u2014 enforces minimum length and complexity (upper and lower case, digits, optionally symbols) for profile updates, registration, and password reset.<\/li>\n<li><strong>Security HTTP headers<\/strong> \u2014 <code>X-Frame-Options<\/code>, <code>X-Content-Type-Options<\/code>, <code>Referrer-Policy<\/code>, <code>Permissions-Policy<\/code>, optionally <code>HSTS<\/code> (use with care \u2014 browsers cache it for a year).<\/li>\n<li><strong>Event log<\/strong> \u2014 records logins (successful and failed), registrations, user changes, plugin activations and deactivations, theme switches, and settings updates. Retention defaults to 30 days. Visible in the admin panel.<\/li>\n<\/ul>\n\n<h4>What makes it different<\/h4>\n\n<ul>\n<li><strong>Modular architecture<\/strong> \u2014 each module is a separate class and can be disabled in the settings without affecting the others.<\/li>\n<li><strong>Zero external dependencies<\/strong> \u2014 no Composer, no vendor lock-in, no cloud APIs.<\/li>\n<li><strong>No data leaves the instance<\/strong> \u2014 everything stays in the local MySQL\/MariaDB database.<\/li>\n<li><strong>Internationalization ready<\/strong> \u2014 full coverage with <code>__()<\/code>\/<code>esc_html__()<\/code> and a POT file for translators.<\/li>\n<li><strong>Clean uninstall<\/strong> \u2014 when the plugin is removed, options, tables, and cron jobs are dropped.<\/li>\n<\/ul>\n\n<h4>What WT Hardening does NOT do (by design)<\/h4>\n\n<ul>\n<li>Does not scan for malware \u2014 that is a different problem, a different toolset.<\/li>\n<li>Does not ship telemetry to the cloud \u2014 all data is local.<\/li>\n<li>Does not add a WAF at the application layer \u2014 that belongs to the server or CDN.<\/li>\n<\/ul>\n\n<p>For those needs we recommend dedicated plugins (e.g. Wordfence) or an infrastructure layer (Cloudflare, fail2ban).<\/p>\n\n<!--section=installation-->\n<h4>Standard install<\/h4>\n\n<ol>\n<li>In the WP admin go to <strong>Plugins \u2192 Add new<\/strong>.<\/li>\n<li>Search for \"WT Hardening\".<\/li>\n<li>Click <strong>Install<\/strong> and then <strong>Activate<\/strong>.<\/li>\n<li>Open the <strong>WT Hardening<\/strong> menu in the admin (shield icon) and configure the modules.<\/li>\n<\/ol>\n\n<h4>Manual install (via ZIP)<\/h4>\n\n<ol>\n<li>Download the archive from <a href=\"https:\/\/wordpress.org\/plugins\/wt-hardening\/\">wordpress.org\/plugins\/wt-hardening<\/a>.<\/li>\n<li>In the WP admin go to <strong>Plugins \u2192 Add new \u2192 Upload plugin<\/strong>.<\/li>\n<li>Pick the downloaded ZIP, click <strong>Install now<\/strong>, and then <strong>Activate plugin<\/strong>.<\/li>\n<\/ol>\n\n<h4>FTP\/SFTP install<\/h4>\n\n<ol>\n<li>Unzip the archive.<\/li>\n<li>Upload the <code>wt-hardening<\/code> folder to <code>wp-content\/plugins\/<\/code> on your server.<\/li>\n<li>In the WP admin go to <strong>Plugins \u2192 Installed plugins<\/strong> and activate <strong>WT Hardening<\/strong>.<\/li>\n<\/ol>\n\n<p>After activation all modules are enabled with sensible defaults. If something clashes with your workflow (for example the Jetpack mobile app that needs XML-RPC), just turn off the specific module in the settings.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20the%20plugin%20modify%20wp-config.php%20or%20.htaccess%3F\"><h3>Does the plugin modify wp-config.php or .htaccess?<\/h3><\/dt>\n<dd><p>No. Everything is wired through WordPress hooks. Deactivating the plugin instantly reverts all changes (except HSTS, which browsers cache \u2014 enabling HSTS is a conscious decision).<\/p><\/dd>\n<dt id=\"will%20blocking%20xml-rpc%20break%20my%20mobile%20app%20%2F%20jetpack%20%2F%20pingbacks%3F\"><h3>Will blocking XML-RPC break my mobile app \/ Jetpack \/ pingbacks?<\/h3><\/dt>\n<dd><p>Possibly, if you actually rely on them. Disable the <strong>XML-RPC<\/strong> module in the settings \u2014 the other protection layers stay active.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20the%20event%20log%20on%20deactivation%3F\"><h3>What happens to the event log on deactivation?<\/h3><\/dt>\n<dd><p>The table stays in the database (useful for later analysis). On full uninstall the tables are dropped cleanly.<\/p><\/dd>\n<dt id=\"does%20the%20plugin%20work%20with%20multisite%3F\"><h3>Does the plugin work with multisite?<\/h3><\/dt>\n<dd><p>Tested on a single-site install. Multisite should work since we do not use superadmin-specific APIs, but it is not yet formally supported \u2014 file an issue if something breaks.<\/p><\/dd>\n<dt id=\"what%20about%20performance%3F\"><h3>What about performance?<\/h3><\/dt>\n<dd><p>Modules only register the hooks they actually need. The event log is a single INSERT per event. No scanner, no background work beyond an hourly and daily cleanup of old rows. Real impact on response time: under 1 ms.<\/p><\/dd>\n<dt id=\"why%20is%20hsts%20disabled%20by%20default%3F\"><h3>Why is HSTS disabled by default?<\/h3><\/dt>\n<dd><p>Because <code>Strict-Transport-Security<\/code> has a <strong>sticky<\/strong> effect \u2014 browsers remember the header for a year. Enabling it too early (before your entire traffic works on HTTPS without errors) can lock users out of the site for a long time. Turn it on once HTTPS is rock-solid.<\/p><\/dd>\n<dt id=\"does%20the%20strong%20password%20policy%20apply%20to%20users%20created%20through%20wp-cli%20or%20%60wp_create_user%28%29%60%3F\"><h3>Does the strong password policy apply to users created through WP-CLI or `wp_create_user()`?<\/h3><\/dt>\n<dd><p>No \u2014 the policy hooks into admin form validation (profile, registration, reset). Programmatic user creation bypasses these hooks by design. For a typical client workflow (users are created through the admin panel) this is enough.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Fix: Plugin URI now points to a public landing page on webmasters.team (the previous URL returned 404 during review).<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fix: readme rewritten in English to satisfy the WordPress.org July 2025 policy.<\/li>\n<li>Fix: escape output in the event log admin page (<code>EventsPage<\/code>).<\/li>\n<li>Fix: replace <code>parse_url()<\/code> with <code>wp_parse_url()<\/code> in the XML-RPC module.<\/li>\n<li>Fix: prefix global variables in <code>uninstall.php<\/code> and add safe-query annotations.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<p>First release.<\/p>\n\n<ul>\n<li>XML-RPC module (endpoint block plus methods filter).<\/li>\n<li>User enumeration blocker for the REST API.<\/li>\n<li>Author archive redirect.<\/li>\n<li>Hide WordPress version.<\/li>\n<li>Remove X-Pingback header.<\/li>\n<li>Generic login error message.<\/li>\n<li>Login attempt limiter with IP lockout.<\/li>\n<li>File editor disable.<\/li>\n<li>Strong password policy (length, mixed case, digits, symbols).<\/li>\n<li>Security HTTP headers (X-Frame, nosniff, Referrer-Policy, Permissions-Policy, HSTS).<\/li>\n<li>Event log (logins, users, plugins, theme, settings) with configurable retention.<\/li>\n<\/ul>","raw_excerpt":"WordPress hardening without touching your theme: XML-RPC, user enumeration, login limiter, security headers, strong passwords, event log.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/304394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=304394"}],"author":[{"embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/webmastersteam"}],"wp:attachment":[{"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=304394"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=304394"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=304394"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=304394"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=304394"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/sv.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=304394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}