=== SolverGuard Security Shield ===
Contributors: solverwp
Tags: security, firewall, login security, malware scanner, audit log
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Firewall, login protection, two-factor, file integrity monitoring, and audit logging, explained in plain language.

== Description ==

SolverGuard Security Shield is a complete security suite for WordPress. Every protection is optional, every option is explained in plain language, and nothing is switched on behind your back.

**A note on what security plugins can and cannot do.** A plugin like this raises the cost of attacking your site: it turns away automated scanners, slows down password guessing, and tells you when something changes. It is not a substitute for keeping WordPress and your plugins updated, using strong unique passwords, and taking backups you have actually tested restoring. Anyone who promises more than that is overselling.

= Login protection =

* Limit failed sign-in attempts per IP address and per username
* Progressive lockouts that lengthen for repeat offenders
* Optional strong-password policy
* A single generic error message, so the login form never confirms which usernames exist
* Sign-in history recording the address, browser, and device for each session

= Firewall =

* SQL injection, cross-site scripting, directory traversal, and code injection detection
* Payloads are decoded before matching, so double-encoded and comment-split evasion still gets caught
* Known vulnerability scanners blocked by user agent
* XML-RPC can be disabled entirely, or limited to blocking pingback amplification
* Username enumeration blocked through both `?author=N` and the REST API
* **Monitor mode** logs what would have been blocked without turning any visitor away — use it before enforcing

= Two-factor authentication =

* Standard time-based codes (TOTP), so any authenticator app works — Google Authenticator, Authy, 1Password, and the rest
* Verified against the official RFC 6238 test vectors, so codes interoperate correctly
* Ten single-use recovery codes per account, stored only as hashes and shown once
* Can be required per role, with a grace period so nobody is locked out mid-rollout
* Each person enrols their own device from their profile, so no administrator ever holds someone else's secret
* Failed codes feed the same lockout counter as failed passwords, so guessing codes is rate limited too

= Country blocking =

Restrict access by country, using Cloudflare's header, WooCommerce's bundled database, or a remote lookup. Two honest caveats, both reflected in the defaults: geolocation is approximate, and a VPN sidesteps it in seconds. So the default scope is the sign-in form only — which cuts remote password guessing without making your content unreadable to a traveller — and visitors whose country cannot be determined are allowed through, because a lookup failure should never become a site outage.

= Scheduled reports =

Runs a file scan on a daily, weekly, or monthly schedule and emails a summary: what changed, how many events were recorded, which addresses are blocked, and which protections are switched off. Distinct from the alert digest — this one actively scans first rather than only recounting what already happened.

= Hide login URL =

Move the sign-in form to a private address so automated scanners never find it. This is obscurity rather than access control, and it works best alongside login limiting rather than instead of it.

= Google reCAPTCHA =

Version 2 checkbox or invisible version 3 scoring, on the sign-in, registration, password reset, and comment forms. Tokens are always verified server-side, and a missing token is treated as a failure — so posting directly to the form does not bypass the check.

= Security headers =

* Content Security Policy, with a report-only mode so you can find breakages before enforcing
* HSTS, with a clear warning that browsers cache the instruction and you cannot revoke it early
* Referrer-Policy, X-Frame-Options, X-Content-Type-Options, and Permissions-Policy

= File integrity and malware defence =

* WordPress core verified against the official checksums published by WordPress.org — stronger than a local baseline, which would simply record an attacker's files as legitimate if taken after a compromise
* Plugin and theme files compared against a baseline you capture when the site is known good
* Executable files in the uploads folder flagged, since nothing legitimate puts them there
* Pattern scanning for the shapes of code that backdoors take, reported for a human to judge rather than acted on automatically

= WooCommerce security =

* Customer sign-in failures counted against the same lockout as the main login form
* Checkout throttling and declined-payment lockouts to stop your shop being used for card testing
* Order and customer data restricted over the REST API
* Order status changes and rejected coupons recorded

= Audit log and login history =

* Role changes, account creation and deletion, plugin and theme changes, key setting changes, and uploads
* A user quietly gaining administrator is recorded as critical
* Filter by severity, event type, user, or IP address; export to CSV
* Configurable retention, and optional IP anonymisation for GDPR
* A separate Login History screen showing every sign-in with its address, browser, device, and session length

= Dashboard =

* Headline counts that refresh themselves while the page is open, and pause when the tab is in the background so a forgotten tab does not keep querying your database
* A 14-day activity chart, drawn in plain CSS so there is no charting library to load and nothing to allow through a Content Security Policy
* Block an address by hand, with your own IP shown for reference and allow-listed addresses refused as a safety net

= Backup and restore =

Export every setting to a JSON file and apply it to another site. Your reCAPTCHA secret key is deliberately left out of the export, so the file is safe to attach to a support ticket. Imports are validated against the same rules as the settings forms, so an edited file cannot introduce unexpected options.

= Alerts =

Email alerts for events that need attention, rate limited per event type and capped per hour so one incident cannot flood your inbox. An optional daily summary covers everything else.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`, or install it through Plugins → Add New.
2. Activate the plugin.
3. Go to **SolverGuard → Dashboard** to see what is switched on.
4. Add your own IP address to the allow list under **Settings → Global access rules** before enabling strict rules. This is the single best way to avoid locking yourself out.
5. If you use a reverse proxy or CDN such as Cloudflare, set the visitor IP source under **Settings → Visitor IP detection**. Leaving it wrong means lockouts and blocklists act on the wrong address.

= Locked out? There is a way back in =

Every protection here can, if misconfigured, shut you out of your own site: a forgotten login address, a lockout on your own IP, a required second factor you never enrolled in. So the plugin ships WP-CLI recovery commands that keep working when the front door does not — the firewall and country blocking deliberately skip WP-CLI requests.

    wp solverguard status              # what is on, and where the sign-in page is
    wp solverguard unblock <ip>        # release one address
    wp solverguard unblock --all       # release every address
    wp solverguard allow <ip>          # allow-list an address permanently
    wp solverguard login-url           # show the custom sign-in address
    wp solverguard login-url --disable # restore /wp-login.php
    wp solverguard 2fa <user> --codes  # issue fresh recovery codes
    wp solverguard 2fa <user>          # remove two-factor from one account
    wp solverguard 2fa --all           # remove two-factor site-wide
    wp solverguard module <id> off     # switch one module off
    wp solverguard panic               # turn off everything that can block access
    wp solverguard scan                # run a file integrity scan

`wp solverguard panic` is the one to remember. It switches off the firewall, login protection, hidden login address, reCAPTCHA, country blocking, and two-factor, and clears every IP block — but keeps your settings, so each module can simply be turned back on once you are in. Non-blocking protections such as security headers and hardening are left running.

== Frequently Asked Questions ==

= Will this lock me out of my own site? =

It can, if configured carelessly — that is true of every security plugin. Add your IP to the allow list first, and start the firewall in Monitor mode.

If you do get locked out and have WP-CLI, run `wp solverguard panic`. Without WP-CLI, rename the plugin's folder over FTP or your host's file manager to deactivate it.

= Does the firewall replace secure coding? =

No. Pattern matching catches known and automated payloads, not novel ones. It buys time and cuts noise; it does not make vulnerable code safe. Keep everything updated.

= Why does the file scanner report changes after every plugin update? =

Because the files genuinely changed. Capture a fresh baseline once you have applied your updates and confirmed the site is working.

= Should I enable HSTS? =

Only once HTTPS works everywhere on your site, including every subdomain if you include them. Browsers remember the instruction for the duration you set and will refuse plain HTTP until it expires. Start with a short duration.

= Why is my Content Security Policy breaking my site? =

Because most themes and plugins rely on inline scripts. Start in report-only mode, watch your browser console, and add what you actually need before switching to enforce.

= Does it work with a proxy or CDN? =

Yes, but you must configure it. Proxy headers can be forged by visitors, so the plugin reads the direct connection address by default and only trusts a proxy header when you opt in and name your trusted proxies.

== External services ==

This plugin can contact three external services. Two of them are only used when
you deliberately switch on the feature that needs them, and neither is contacted
at all until then. Each is described below with what is sent, when, and why.

= WordPress.org core checksums =

The file integrity scanner compares your WordPress core files against the
official checksums published by WordPress.org, so it can tell you if a core file
has been altered. When a core scan runs — either from the File Integrity screen
or on the schedule you set — the plugin asks WordPress.org for the checksum list
matching your WordPress version and locale. It uses the `get_core_checksums()`
function built into WordPress, which is the same mechanism WordPress core itself
uses.

What is sent: your WordPress version number and locale. No personal data, no
site address, and no file contents are transmitted; the comparison happens
entirely on your own server.

When: only while a core file integrity scan is running.

Service: WordPress.org — https://api.wordpress.org/core/checksums/1.0/
Terms of service: https://wordpress.org/about/privacy/
Privacy policy: https://wordpress.org/about/privacy/

= Google reCAPTCHA =

Used only if you enable reCAPTCHA and enter your own site key and secret key.
When enabled, the plugin loads Google's reCAPTCHA script on the forms you have
chosen to protect, and verifies the resulting token with Google's servers on
submission.

What is sent: on page load, your site key, and whatever the reCAPTCHA script
itself collects from the visitor's browser as part of Google's bot assessment.
On form submission, your secret key, the reCAPTCHA token, and the visitor's IP
address are sent to Google's verification endpoint.

When: on any page that shows a protected form, and again when that form is
submitted. Never if the feature is switched off, which is the default.

Because this sends visitor data to Google, you may need to mention it in your
own privacy policy. The feature is off by default so that decision stays yours.

Service: Google reCAPTCHA — https://www.google.com/recaptcha/api.js and
https://www.google.com/recaptcha/api/siteverify
Terms of service: https://policies.google.com/terms
Privacy policy: https://policies.google.com/privacy

= ipapi.co =

Used only if you enable country blocking and no local geolocation database is
available on your server. It turns a visitor's IP address into a two-letter
country code so the country rules you configured can be applied.

What is sent: the visitor's IP address, and nothing else. The result is cached
for a week, so a repeat visitor from the same address is not looked up again.

When: the first time an unrecognised IP address is checked against your country
rules, and only while country blocking is switched on — which it is not by
default.

Because this sends visitor IP addresses to a third party, you may need to
mention it in your own privacy policy.

Service: ipapi.co — https://ipapi.co/
Terms of service: https://ipapi.co/terms/
Privacy policy: https://ipapi.co/privacy/

== Screenshots ==

1. The security dashboard, showing current status and recent activity.
2. Firewall settings, with monitor mode and per-rule controls.
3. The audit log, filterable by severity, event type, and IP address.
4. File integrity results after a scan.

== Changelog ==

= 1.0.1 =

Changes made in response to the WordPress.org plugin review.

* Sign-in history no longer derives its session identifier from the WordPress
  authentication cookie. It now uses an identifier the plugin generates itself,
  kept in its own cookie, so no authentication material is read or stored. The
  old column is dropped when you update; existing history rows are kept.
* The blocked-request page is now rendered by `wp_die()` instead of a page this
  plugin built by hand, which removes the inline stylesheet it used to emit.
  Blocked XML-RPC and REST requests are now refused in the format their client
  expects rather than always receiving HTML.
* Hardening no longer defines WordPress core constants. Disabling the file
  editor and blocking plugin or theme installation are now applied by
  withholding the relevant capabilities, and forcing HTTPS in the admin area is
  applied by a redirect. All three stay scoped to this plugin's settings and
  stop the moment a setting is switched off, instead of changing behaviour
  globally for the rest of the request.
* The readme now documents every external service the plugin can contact —
  WordPress.org core checksums, Google reCAPTCHA, and ipapi.co — with what is
  sent, when it is sent, and links to each service's terms and privacy policy.
* Corrected the contributor username in the readme.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.0.1 =
Addresses the WordPress.org review feedback. The sign-in history table changes
shape on update: the old session column is removed and its contents discarded.
Your history entries themselves are preserved.

= 1.0.0 =
Initial release.
