=== WP Chest - Security ===
Contributors: squidspark
Tags: security, two-factor, 2fa, totp, xmlrpc, https, login url, updates
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.0.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Hardening for self-hosted WordPress: a custom login URL, XML-RPC off, forced HTTPS, two-factor authentication, and a daily out-of-date report.

== Description ==

Five things every self-hosted WordPress site should have, with no upsells, no phone-home, and no third-party libraries — WordPress core APIs only.

**1. Move the login URL.** wp-login.php is the same address on every WordPress site, which makes it a standing target. Serve it from a slug of your choosing instead; the original 404s (or bounces home), and wp-admin stops answering logged-out visitors so its redirect can't be used to discover the new address.

**2. Turn off XML-RPC.** The endpoint answers nothing at all — not a fault, not a 200. system.multicall lets one request try hundreds of passwords and pingback.ping turns a site into a reflector for attacks on other hosts. If something you run genuinely needs XML-RPC, keep the endpoint and drop just the pingback methods.

**3. Force HTTPS.** Plain HTTP requests are redirected to the same URL over HTTPS, with optional HSTS. Forwarded-protocol headers are read (behind a setting) so a TLS-terminating proxy or CDN doesn't cause a redirect loop, and the redirect target is validated against the site's own hosts so a forged Host header can't turn it into an open redirect.

**4. Two-factor authentication on local logins.** Three methods:

* **Authenticator app (TOTP)** — RFC 6238, six digits, 30 seconds. The enrolment QR code is generated on your own server; the secret never leaves it.
* **Email code** — a one-time code to the account's address.
* **SMS code** — a one-time code by text, via Twilio, Vonage, MessageBird or your own webhook.

Plus single-use backup codes, per-role requirements with a grace period, and enrolment that only completes once a code produced by the new method has been typed back in — so nobody locks themselves out with a mistyped secret or phone number.

Single sign-on, application passwords and existing cookie sessions are untouched. A password login over XML-RPC or the REST API is refused outright rather than allowed past the prompt.

**5. Daily out-of-date report.** Once a day (or weekly), check WordPress, plugins and themes against WordPress.org and email whoever should be doing something about it. Out-of-date plugins are how most compromised WordPress sites get compromised, and the update badge in wp-admin only helps people who are already logged in.

= Email and SMS providers =

Two-factor codes and update reports are only useful if they arrive. Configure SMTP, SendGrid, Mailgun or Postmark for email — for this plugin's messages only, or for all site email — and Twilio, Vonage, MessageBird or a custom webhook for SMS. Credentials are write-only in the UI and each provider has a "send a test" button.

= If you lock yourself out =

Every feature that can lock someone out has an escape hatch that works over FTP or SSH with no database access. Add any of these to `wp-config.php`:

* `define( 'WPCSEC_SAFE_MODE', true );` — disarms all three at once
* `define( 'WPCSEC_DISABLE_LOGIN_SLUG', true );` — wp-login.php answers again
* `define( 'WPCSEC_DISABLE_HTTPS_REDIRECT', true );`
* `define( 'WPCSEC_DISABLE_2FA', true );`

Deactivating the plugin also restores everything: the login slug, the XML-RPC block and the HTTPS redirect all stop simply because the code stops running.

== Installation ==

1. Upload the `wp-chest-security` folder to `/wp-content/plugins/`.
2. Activate it. Nothing that can lock you out is switched on by installing — every such feature is off until you turn it on.
3. Go to **Security** and work through the tabs.

== Frequently Asked Questions ==

= Does the QR code get sent to a third party? =

No. It is drawn by a QR encoder inside the plugin, in PHP. The TOTP secret never leaves your server.

= What happens to users who lose their phone? =

They can sign in with a backup code, or an administrator can clear their second factors from the user's profile screen and let them enrol again.

= Will this break my mobile app or my publishing client? =

If it uses XML-RPC, set XML-RPC to "Enabled, without pingbacks" rather than off. If it signs in with a username and password over the REST API, give it an application password instead — those bypass the two-factor prompt by design.

= Does the custom login URL work without pretty permalinks? =

Yes. With pretty permalinks it is a path (`/your-slug/`); without them it becomes `/?your-slug`, because there are no rewrite rules to route a path.

== Changelog ==

= 1.0.0 =
* Initial release: custom login URL, XML-RPC control, forced HTTPS with HSTS, two-factor authentication (TOTP, email, SMS, backup codes), email and SMS provider settings, and scheduled out-of-date reports.
