=== WT Hardening ===
Contributors: webmastersteam
Donate link: https://webmasters.team/
Tags: security, hardening, brute-force, xmlrpc, security-headers
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 8.0
Stable tag: 1.0.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

WordPress hardening without touching your theme: XML-RPC, user enumeration, login limiter, security headers, strong passwords, event log.

== Description ==

**WT Hardening** is a lightweight, modular security plugin that turns on the most important WordPress hardening measures without modifying your theme, `wp-config.php`, or `.htaccess`. Everything works through WordPress hooks and can be disabled at any moment with a single click.

The plugin is **completely free**, without a PRO version, without ads, and without sending data to external servers. Built by the [webmasters.team](https://webmasters.team) crew for daily WordPress work.

= Modules =

* **XML-RPC** — blocks `xmlrpc.php` (403) and filters the XML-RPC methods. Stops brute-force attacks through the most attacked WordPress endpoint.
* **User enumeration** — hides logins by blocking `/wp/v2/users` in the REST API for unauthenticated users.
* **Author archive** — redirects `/?author=1` to the homepage (another enumeration vector).
* **Hide WP version** — removes the `<meta name="generator">` tag, `?ver=` query strings from assets, and redundant meta tags (wlwmanifest, rsd, shortlink).
* **X-Pingback** — removes the `X-Pingback` HTTP header from all responses.
* **Login errors** — replaces the specific "wrong login / wrong password" messages with a single generic text (does not reveal whether a login exists).
* **Login limiter** — blocks an IP for X minutes after N failed attempts. Data lives in a dedicated table (not `wp_options`), with hourly cleanup of old entries.
* **File editor** — sets `DISALLOW_FILE_EDIT`, hiding the theme and plugin editor in the admin (an attacker who compromises an account cannot inject a backdoor through the browser).
* **Password policy** — enforces minimum length and complexity (upper and lower case, digits, optionally symbols) for profile updates, registration, and password reset.
* **Security HTTP headers** — `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`, optionally `HSTS` (use with care — browsers cache it for a year).
* **Event log** — 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.

= What makes it different =

* **Modular architecture** — each module is a separate class and can be disabled in the settings without affecting the others.
* **Zero external dependencies** — no Composer, no vendor lock-in, no cloud APIs.
* **No data leaves the instance** — everything stays in the local MySQL/MariaDB database.
* **Internationalization ready** — full coverage with `__()`/`esc_html__()` and a POT file for translators.
* **Clean uninstall** — when the plugin is removed, options, tables, and cron jobs are dropped.

= What WT Hardening does NOT do (by design) =

* Does not scan for malware — that is a different problem, a different toolset.
* Does not ship telemetry to the cloud — all data is local.
* Does not add a WAF at the application layer — that belongs to the server or CDN.

For those needs we recommend dedicated plugins (e.g. Wordfence) or an infrastructure layer (Cloudflare, fail2ban).

== Installation ==

= Standard install =

1. In the WP admin go to **Plugins → Add new**.
2. Search for "WT Hardening".
3. Click **Install** and then **Activate**.
4. Open the **WT Hardening** menu in the admin (shield icon) and configure the modules.

= Manual install (via ZIP) =

1. Download the archive from [wordpress.org/plugins/wt-hardening](https://wordpress.org/plugins/wt-hardening/).
2. In the WP admin go to **Plugins → Add new → Upload plugin**.
3. Pick the downloaded ZIP, click **Install now**, and then **Activate plugin**.

= FTP/SFTP install =

1. Unzip the archive.
2. Upload the `wt-hardening` folder to `wp-content/plugins/` on your server.
3. In the WP admin go to **Plugins → Installed plugins** and activate **WT Hardening**.

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.

== Frequently Asked Questions ==

= Does the plugin modify wp-config.php or .htaccess? =

No. Everything is wired through WordPress hooks. Deactivating the plugin instantly reverts all changes (except HSTS, which browsers cache — enabling HSTS is a conscious decision).

= Will blocking XML-RPC break my mobile app / Jetpack / pingbacks? =

Possibly, if you actually rely on them. Disable the **XML-RPC** module in the settings — the other protection layers stay active.

= What happens to the event log on deactivation? =

The table stays in the database (useful for later analysis). On full uninstall the tables are dropped cleanly.

= Does the plugin work with multisite? =

Tested on a single-site install. Multisite should work since we do not use superadmin-specific APIs, but it is not yet formally supported — file an issue if something breaks.

= What about performance? =

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.

= Why is HSTS disabled by default? =

Because `Strict-Transport-Security` has a **sticky** effect — 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.

= Does the strong password policy apply to users created through WP-CLI or `wp_create_user()`? =

No — 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.

== Screenshots ==

1. Settings panel — modules rendered as cards with toggles and descriptions.
2. Login attempt log — currently blocked IPs plus a list of recent failed attempts.
3. Event log — chronology of logins, registrations, user changes, and plugin activations.

== Changelog ==

= 1.0.2 =
* Fix: Plugin URI now points to a public landing page on webmasters.team (the previous URL returned 404 during review).

= 1.0.1 =
* Fix: readme rewritten in English to satisfy the WordPress.org July 2025 policy.
* Fix: escape output in the event log admin page (`EventsPage`).
* Fix: replace `parse_url()` with `wp_parse_url()` in the XML-RPC module.
* Fix: prefix global variables in `uninstall.php` and add safe-query annotations.

= 1.0.0 =
First release.

* XML-RPC module (endpoint block plus methods filter).
* User enumeration blocker for the REST API.
* Author archive redirect.
* Hide WordPress version.
* Remove X-Pingback header.
* Generic login error message.
* Login attempt limiter with IP lockout.
* File editor disable.
* Strong password policy (length, mixed case, digits, symbols).
* Security HTTP headers (X-Frame, nosniff, Referrer-Policy, Permissions-Policy, HSTS).
* Event log (logins, users, plugins, theme, settings) with configurable retention.

== Upgrade Notice ==

= 1.0.2 =
Plugin URI fix — points to the new landing page on webmasters.team. No code or behavior changes.

= 1.0.1 =
Compliance update: readme translated to English, escape fixes, safer URL parsing. No data or behavior changes.

= 1.0.0 =
First release — install, activate, modules are enabled with sensible defaults.
