SecureLite Security — changelog, 0.1.0 to 0.2.12

Newer versions are listed in readme.txt and on the plugin page at WordPress.org.

= 0.2.12 =
* SecureLite no longer writes .htaccess files. The uploads protection now shows the exact rule for Apache/LiteSpeed and for nginx to add yourself (or hand to your host), and recognises it — or an equivalent your host added — once it is there. Rules applied by an earlier version are left in place.
* Attack Simulation's "PHP execution blocked in uploads" check writes nothing: it requests a .php address in uploads that does not exist and reports whether the server refused it before WordPress ran.
* Every file and folder location is now resolved from WordPress functions (get_home_path(), plugin_dir_path(), wp_upload_dir(), content_url() and others) instead of internal constants, so sites with WordPress in its own subdirectory or a moved content folder are scanned and reported correctly. The site root's .htaccess and index.php are watched in the home folder, where WordPress keeps them.
* The folder earlier versions kept in uploads (Attack Simulation samples) is removed on update.

= 0.2.11 =
* Malware scan now compares every WordPress core file with the official checksums from WordPress.org. Any PHP file added to wp-admin or wp-includes, and any changed core file, is reported as Critical; an unknown PHP file in the site root is reported, and Critical if it also matches a malware pattern. Found on a real hacked site: nine web shells in the site root and in wp-includes/js that the previous scan never looked at.
* Scanner hits in wordpress.org plugins are checked against that plugin's official release. Files identical to the release are cleared (stock elFinder, phpunit and similar library code was being reported as a backdoor); changed or added files are raised to Critical. Premium and custom plugins are marked as not verifiable.
* Genuine WordPress files from another release are no longer reported as malware. When new WordPress files were copied over an old install, an update stopped half way, or PHP's OPcache is still running the old version, core files are compared with the version written on disk, then with the newest release and the releases this site ran before; matching files are grouped into one plain finding ("an update did not finish", "left over from WordPress X") instead of one Critical per file. A file at a genuine WordPress path with altered content is still Critical.
* PHP files with unusual extensions (.php56, .php8, .PhP7 …) are now scanned.
* Packed payloads wrapped in another call before the decoder, such as eval(implode(…, gzinflate(base64_decode(…)))), are now Critical instead of Suspicious.
* The dashboard says when a scan stopped at its time or file limit, so a partial scan is never read as an all-clear.
* Attack Simulation on hosts with their own firewall (LiteSpeed, Imunify360, ModSecurity): WordPress now tags its answers to the simulation's probes, so an answer from the host is recognised. A probe the host refused (for example HTTP 444) is reported as blocked by your hosting server instead of failed; a dropped connection or a page-cache answer is reported as could not be tested, with the reason, and no longer shows an Enable & re-test button that could not change anything. Previously these hosts showed three failures on first run.
* Attack Simulation's brute-force check now still tests the lockout when the host refuses its test logins, cuts them off early, or this site's own address is a trusted IP. It runs SecureLite's lockout inside WordPress instead, from a reserved documentation address (192.0.2.0/24) so your own address is never locked, and confirms the lock trips at your limit and holds against a different username and against a correct password. Previously this check was skipped on those hosts, and its message suggested the host was already blocking bots, which a host filter only partly does.
* A failed brute-force check no longer offers Enable & re-test when login protection is already on.

= 0.2.10 =
* Fixed: Regenerate keys and salts could write a key containing "$" followed by a digit in a way that broke wp-config.php with a syntax error, taking the site offline. Keys are now written literally, and every wp-config.php change is checked to be valid PHP before it is saved — an edit that would not parse is refused.
* Security: SecureLite no longer copies wp-config.php anywhere. Edits to it (the file-editor switch, the trusted-IP line, Regenerate keys and salts) are written in place, read back and checked, and the original is restored from memory if the write did not land exactly. Every backup copy left by earlier versions — beside wp-config.php, under wp-content/securelite-backups or under uploads — is deleted on update.
* Attack Simulation never writes a PHP file. The malware-scanner check tests the real signatures and scan coverage against samples held in memory; the uploads check confirms SecureLite's rule is present and proves the server obeys .htaccess in uploads using a plain-text file. The configuration-backup check is removed, as there are no backups to expose.
* Rate-limiter and crawler-cache transients now use the plugin's full prefix.
* The "recovery codes running low" notice appears only on the Dashboard, your profile and SecureLite's screens.

= 0.2.8 =
* Security: the per-address lockout did not hold. WordPress's own password check replaced SecureLite's refusal, so a locked address saw the "too many failed attempts" message but could still sign in with the right password, or keep guessing under a different username. A locked address is now refused for the whole lockout window, whatever the password or username. The per-username lock is unchanged: the right password from another address still gets in.
* "PHP execution blocked in uploads" can now be fixed from the Verification screen with Enable & re-test, which writes the uploads rule and re-runs the check. If the rule is already there but PHP still runs, the result says your server is ignoring .htaccess and what to change, instead of sending you back to apply it again.
* Fixed: an uploads .htaccess holding only an empty SecureLite block, left behind after deactivating an older version, counted as protection. The check then blamed the server for ignoring .htaccess and hid the fix button. SecureLite now looks for the actual rule, and deactivating no longer leaves an empty block (or an empty file) behind.
* Fixed: the uploads rule included "Options -Indexes", which returns a 500 error for every image in uploads on hosts that don't allow that directive. It is removed, the rule now also works on Apache 2.2, and sites that already applied the old rule get the new one automatically.
* Attack Simulation now runs live: each attack goes out one at a time and you watch every protection answer, with a progress bar and the result appearing on each row. When it finishes the results stay on screen in the same design, with Enable & re-test on anything that can be fixed and a print/save button; the saved report uses the same layout. Enable & re-test now re-runs the same live view, so you watch the fix turn green.
* Repeat offenders are locked out longer. An address locked again within a day waits at least 1 hour, and after that at least 24 hours, so a bot that returns whenever a lock lifts gets a handful of guesses a day instead of hundreds. A person who mistypes once still waits only the normal window, and signing in successfully clears the address's history. Username locks never escalate.
* A repeat offender posting to the login form is refused with HTTP 429 and a Retry-After header before WordPress does any login work, which saves server resources under a sustained attack. A first-time lockout still shows the normal login screen.
* The lockout message now says how long login is paused, instead of "try again later", and links to a help page on getting back into your own site. It shows no recovery details itself, because attackers see it too, and it reads the same for an address lock and a username lock.
* Attack Simulation's brute-force check now also tries a fresh username from the locked address, and fails if that attempt is not refused, so this kind of gap cannot pass the check again.
* Security: with "Behind a proxy/CDN" on, a forwarded IP header was believed from any connection, so an attacker could send a fake X-Forwarded-For and dodge the lockout, or claim a trusted IP. Forwarded headers are now only read when the connection comes from a trusted proxy: your private network, Cloudflare's edges (new preset), or addresses you list. X-Forwarded-For is read from the right, so the address a client claims for itself is never taken on trust.
* Sites that already had proxy mode on get the Cloudflare preset switched on during the update, so visitors keep their real addresses.
* The settings screen shows which address SecureLite sees you connecting from and where it read it, and warns when Cloudflare traffic arrives with proxy mode off. Both problems also appear as posture findings.
* Fixed: in block mode the firewall could refuse an editor's or author's post that mentioned `javascript:`, `onclick=` or `document.cookie`, losing the draft. Content saved through wp-admin, admin-ajax or the REST API by users who can edit posts is no longer signature-matched; their URLs, cookies and uploads still are.
* Fixed: any form field containing the text "wp-config.php" was treated as a traversal attack. It now only matches when the whole value is a path to the file.
* Firewall log entries now record the role of the user who tripped them.
* One click to add your IP to wp-config.php as the lockout escape hatch. wp-config.php is backed up first, the change is read back to confirm it landed, and an existing SECURELITE_ALLOW_IP line is added to rather than duplicated. If the file cannot be written, the message says why — locked permissions, the file not found, or a definition SecureLite should not rewrite — and gives you the line to add by hand. Deactivating removes the line and reactivating puts it back, like SecureLite's other wp-config.php changes.
* SecureLite refuses to trust a Cloudflare address, whether from that button or typed into Trusted IPs, because it is shared by huge numbers of visitors. It tells you to set up proxy mode instead.
* Three ways back in after a lockout — a wp-config.php line with your current IP already filled in, a folder rename, and a WP-CLI command — are now on the Support screen and one click away under Login protection. They are also emailed to you once, the first time you save with a lockout feature on, and the save message tells you it was sent.
* SecureLite now shows an admin notice and stops loading, instead of causing a fatal error, if the server is later moved to a PHP or WordPress version older than it supports.
* Recovery → Reset passwords now shows exactly whose passwords it will reset, with a count and the usernames in the confirmation. When you are the only administrator it says so instead of reporting "Reset 0 password(s)", and links to your profile to change your own password.
* Security: resetting a password now also signs that account out everywhere and deletes its application passwords, which keep working for the REST API after a password change. It can email each account a link to choose a new password, and says plainly if the server could not send mail.
* Requires WordPress 6.2 or newer.

= 0.2.7 =
* SecureLite now removes what it added. Deactivating the plugin takes back the two changes it makes outside its own database — the rule in your uploads .htaccess and the DISALLOW_FILE_EDIT line in wp-config.php — and activating it again puts them back exactly as they were. Uninstalling removes them for good.
* It only ever undoes its own work. A DISALLOW_FILE_EDIT line that was in wp-config.php before you installed SecureLite is restored to its original text rather than deleted, and one that another plugin manages is not touched at all.
* Your settings, trusted IPs and security log are never touched by deactivation. Deactivating a plugin is how people troubleshoot, and it should not cost them their configuration.
* Security: the per-username lockout could be used against you. Anyone who knew an administrator's username could hold that account shut for everyone not on the trusted-IP list — including the real administrator, on mobile data, who then could not log in to add their address. The username lock is now decided after the password has been checked: a wrong password is refused exactly as before, and a correct one gets in and clears the lock. Guessing gains an attacker nothing, and someone who already has your password was never what this counter was protecting you from.
* A per-username lock is now capped at 30 minutes however long your lockout window is set. It is the one counter a stranger can drive up deliberately, so its duration is not theirs to choose.
* The system report now shows both lock durations.

= 0.2.6 =
* The system report on the Support screen now answers "why was I not locked out?" — it shows your own address and whether it is trusted, the live failure counts against their thresholds, when the current window opened, and when any active lock expires.
* The report also lists every plugin that has a hand in your login, in the order they run. A second security plugin answering the login before SecureLite is the quiet cause of half the reports that a lockout does nothing, and it was previously invisible.
* Added a Common problems entry for the same question, with the four causes in the order they turn out to be true.
* Fixed: the report still quoted the old rate-limiting defaults (block mode, 120 requests a minute) rather than the ones shipped since 0.2.2.

= 0.2.5 =
* Settings switches are now toggles rather than checkboxes, so the state of each protection reads at a glance.
* The theme and plugin file editor setting now detects when another plugin already controls it. Rather than showing a switch that would change nothing, it locks, shows what is actually true on your site, and explains where to change it.

= 0.2.4 =
* Added email notifications, sent by your own site with no external service involved. A daily summary plus an immediate email for two findings only: malware detected, or a watched file changed.
* SecureLite never sends one email per blocked request. That traffic is counted and summarised, never itemised, and the summary reports numbers of addresses rather than lists of them.
* On a quiet day, no summary is sent. An email that says nothing happened is how people learn to ignore a sender.
* Immediate alerts are limited to one per hour and only fire for a finding that is new — a condition that is still true tomorrow is not a new alert.
* Notifications can be set to summary-plus-alerts, alerts only, or off entirely. The local security log keeps recording either way.

= 0.2.3 =
* Two-factor authentication can no longer be switched on by ticking a box. You must enter a code your authenticator app produced, and if it is not accepted nothing changes and you stay signed in.
* Two-factor now issues ten single-use recovery codes at setup, shown once, stored hashed. Any of them will sign you in if you lose your phone, and you are warned when three or fewer remain.
* The setup secret is now kept between page loads, so scanning the QR code and then reloading the page no longer silently invalidates it.
* Changing your login URL is now proved before it is kept: the new address is requested over loopback, and if it does not return a login form the setting switches itself back off and tells you why. The new address is also emailed to the site administrator.
* Login slugs that collide with an existing page, post or category are refused, along with slugs under three characters.
* Attack Simulation gained a fourteenth check: it plants an inert file in the configuration backup directory, asks the server for it, and fails if the server hands it over.

= 0.2.2 =
* Security: wp-config.php backups were written next to wp-config.php in the site root, where a default server configuration serves them as plain text. They are now kept under wp-content in a protected directory with an unguessable filename, only the three most recent are retained, and any backup left in the site root by an earlier version is deleted automatically on update.
* Fixed: being asked for a two-factor code counted as a failed login, so users with two-factor enabled could be locked out of their own site while entering the correct password. Wrong authenticator codes now have their own, more forgiving budget.
* Fixed: retrying while locked out extended the lockout by the full window each time.
* Verified search-engine crawlers (Google, Bing, Yandex, Baidu, DuckDuckGo, Apple) are no longer rate limited. Each is confirmed by forward-confirmed reverse DNS, so a spoofed user-agent gains nothing. robots.txt and sitemaps are always served.
* Rate limiting now ships in monitor mode, and the default allowance is 240 requests per minute rather than 120. A per-IP cap also counts everyone sharing one address, so the log should be reviewed before it starts turning requests away.
* SecureLite now refuses to edit wp-config.php at all if it cannot write a backup first.

= 0.2.1 =
* SecureLite now runs entirely on your own site. The optional cloud transport has been removed along with its settings, so the plugin makes no outbound connections of any kind.
* Added a trusted-IP allowlist (exact address or CIDR, IPv4 and IPv6) exempting the brute-force lockout and rate limiter.
* Added the SECURELITE_ALLOW_IP wp-config constant so an administrator who is locked out can recover with file access alone.
* Added a tenth verification probe that plants an inert malware sample and confirms the scanner flags it, then removes it.
* Fixed: the rate limiter accepted an unvalidated authentication cookie name as proof of login.
* Admin interface refinements and cache-busted stylesheets.

= 0.2.0 =
* Added the request firewall (SQL injection, XSS, directory traversal, scanner signatures) with monitor and block modes.
* Added malware, JavaScript-injection and database scanning.
* Added the executable-upload virtual patch.
* Added rate limiting and Heartbeat API throttling.
* Added the hidden login URL, uploads hardening, post-hack recovery toolkit and Run Attack Simulation.

= 0.1.0 =
* Initial release: login hardening, TOTP two-factor, signal collection, file-integrity monitoring, posture scoring, heartbeat.
