{"id":325268,"date":"2026-06-23T22:50:19","date_gmt":"2026-06-23T22:50:19","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/ghostables-defender-lite\/"},"modified":"2026-06-23T23:06:04","modified_gmt":"2026-06-23T23:06:04","slug":"ghostables-defender-lite","status":"publish","type":"plugin","link":"https:\/\/twd.wordpress.org\/plugins\/ghostables-defender-lite\/","author":23515434,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.1.6","stable_tag":"0.1.6","tested":"7.0","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Ghostables Defender Lite","header_author":"Ghostables Ltd","header_description":"Free, fully functional security for WordPress \u2014 vulnerability scanning, file integrity, a hardening checklist, a tamper-evident audit log, two-factor authentication, and an operator gate. Nothing is locked or limited.","assets_banners_color":"34484c","last_updated":"2026-06-23 23:06:04","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/ghostables.io\/plugins\/defender","header_author_uri":"https:\/\/ghostables.io","rating":0,"author_block_rating":0,"active_installs":0,"downloads":53,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.1.5":{"tag":"0.1.5","author":"ghostables","date":"2026-06-23 22:49:53"},"0.1.6":{"tag":"0.1.6","author":"ghostables","date":"2026-06-23 23:06:04"}},"upgrade_notice":{"0.1.6":"<p>Fixes the scan progress modal appearing hidden behind its backdrop. No functional changes.<\/p>","0.1.5":"<p>Scan-control REST endpoints now enforce the Operator gate in their permission_callback. No change to the security features themselves.<\/p>","0.1.4":"<p>Guidelines compliance: retention is now a free setting, no features are gated, and all JS\/CSS is enqueued. No change to the security features themselves.<\/p>","0.1.3":"<p>Plugin Check round-2 cleanup. No functional changes.<\/p>","0.1.2":"<p>Plugin Check \/ WordPress.org coding-standards cleanup. No functional or behavioural changes.<\/p>","0.1.1":"<p>Security hardening release. Removes third-party transmission of the 2FA secret, closes XML-RPC\/application-password bypass for 2FA users, hashes recovery codes, adds brute-force throttling, and upgrades the audit chain to HMAC. Upgrade promptly.<\/p>","0.1.0":"<p>First release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3583851,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3583851,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3583851,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3583851,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.1.5","0.1.6"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Six-card security dashboard.","2":"Vulnerability scan results.","3":"File-integrity drift findings with re-baseline.","4":"Hardening checklist with one-click fixes.","5":"Tamper-evident audit log.","6":"\"More Security\" page \u2014 information about the separate Ghostables Defender plugin.","7":"Setup wizard."}},"plugin_section":[],"plugin_tags":[168808,31093,600,1909,139069],"plugin_category":[54],"plugin_contributors":[268617],"plugin_business_model":[],"class_list":["post-325268","plugin","type-plugin","status-publish","hentry","plugin_tags-file-integrity","plugin_tags-hardening","plugin_tags-security","plugin_tags-two-factor-authentication","plugin_tags-vulnerability-scanner","plugin_category-security-and-spam-protection","plugin_contributors-ghostables","plugin_committers-ghostables"],"banners":{"banner":"https:\/\/ps.w.org\/ghostables-defender-lite\/assets\/banner-772x250.png?rev=3583851","banner_2x":"https:\/\/ps.w.org\/ghostables-defender-lite\/assets\/banner-1544x500.png?rev=3583851","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/ghostables-defender-lite\/assets\/icon-128x128.png?rev=3583851","icon_2x":"https:\/\/ps.w.org\/ghostables-defender-lite\/assets\/icon-256x256.png?rev=3583851","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>Ghostables Defender Lite<\/strong> is a free, fully functional security plugin for WordPress. Nothing in it is locked, limited, or gated behind a licence \u2014 every feature below works out of the box:<\/p>\n\n<ul>\n<li>Continuous vulnerability scanning against installed plugins, themes, and WordPress core<\/li>\n<li>Cryptographic file integrity baseline with daily drift detection<\/li>\n<li>WordPress hardening checklist with one-click safe fixes<\/li>\n<li>Per-user TOTP two-factor authentication (Google Authenticator, Authy, 1Password)<\/li>\n<li>Tamper-evident audit log \u2014 events are linked together so any deletion is detectable, with a free, user-configurable retention period<\/li>\n<li>Operator gate \u2014 a PIN above WordPress admin so a compromised super-admin cannot silently disable the plugin<\/li>\n<\/ul>\n\n<p>Built by <a href=\"https:\/\/ghostables.io\">Ghostables Ltd<\/a>. Opinionated about defaults. Honest about what each setting actually does.<\/p>\n\n<h4>Is anything locked or limited?<\/h4>\n\n<p>No. Defender Lite is free and complete \u2014 no nag screens, no crippled features, no trial period, no usage quota. The audit-log retention period is a setting you control (default 90 days; set it to keep everything forever). Every feature listed above is the real thing.<\/p>\n\n<h4>Is there a more advanced version?<\/h4>\n\n<p>Yes \u2014 <strong>Ghostables Defender<\/strong> is a separate, more advanced plugin distributed from <a href=\"https:\/\/ghostables.io\">ghostables.io<\/a>. It is not part of this plugin and is not required to use Defender Lite. It adds capabilities such as a behavioural firewall, malware quarantine, Cloudflare edge sync, webhook alerts, encrypted backups, and more. The \"More Security\" page inside Defender Lite lists what it adds, purely for information.<\/p>\n\n<h4>Coexistence with the separate plugin<\/h4>\n\n<p>If you install the separate Ghostables Defender plugin, Defender Lite steps aside automatically so the two don't run side by side. Your settings (Operator PIN, hardening fixes, baseline, audit chain) are preserved across the handover. Defender Lite remains free and fully functional whether or not you ever install it.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to one external service: the public WordPress Vulnerability Database operated by the WPVulnerability project at <code>https:\/\/www.wpvulnerability.net\/<\/code>.<\/p>\n\n<ul>\n<li><strong>What is sent:<\/strong> an HTTP GET request to <code>https:\/\/www.wpvulnerability.net\/plugin\/{slug}\/<\/code>, <code>https:\/\/www.wpvulnerability.net\/theme\/{slug}\/<\/code>, or <code>https:\/\/www.wpvulnerability.net\/core\/{wp-version}\/<\/code> \u2014 one URL per installed component being checked. The request body is empty. The only request headers are <code>Accept: application\/json<\/code> and a User-Agent of the form <code>GhostablesDefenderLite\/&lt;plugin version&gt;<\/code>. No site URL, no admin email, no IP-derived identifier \u2014 only the slug of the component being queried and the User-Agent itself.<\/li>\n<li><strong>What is received:<\/strong> a JSON record listing publicly disclosed vulnerabilities affecting that single component, with affected version ranges and severity scores. The plugin compares this against the locally-installed version and stores any open findings in the plugin's own database table.<\/li>\n<li><strong>When it is sent:<\/strong> at most once per installed component per 24 hours. Each per-slug response is cached locally in a WordPress transient, so the twice-daily scan cron only triggers fresh HTTP requests when the cache has expired.<\/li>\n<li><strong>Service provider:<\/strong> The WPVulnerability Project (operated by ROBOTSTXT and contributors). Service licence (EUPL v1.2, GPL-compatible): <a href=\"https:\/\/www.wpvulnerability.com\/license\/\">https:\/\/www.wpvulnerability.com\/license\/<\/a>. Privacy policy: <a href=\"https:\/\/www.wpvulnerability.com\/privacy\/\">https:\/\/www.wpvulnerability.com\/privacy\/<\/a>.<\/li>\n<\/ul>\n\n<p>No other outbound network traffic originates from this plugin. The two-factor QR code is rendered locally in the operator's browser using a vendored MIT-licensed JavaScript library \u2014 the TOTP secret is never transmitted to any third party.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload <code>ghostables-defender-lite<\/code> to <code>\/wp-content\/plugins\/<\/code> (or install via Plugins \u2192 Add New)<\/li>\n<li>Activate<\/li>\n<li>Follow the 4-step setup wizard. The first administrator to complete it becomes the founding <strong>Operator<\/strong> \u2014 sets a 6\u201310 digit PIN and receives 10 single-use recovery codes.<\/li>\n<li>The wizard takes the first file-integrity baseline and runs the first vulnerability scan automatically.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20defender%20lite%20phone%20home%3F\"><h3>Does Defender Lite phone home?<\/h3><\/dt>\n<dd><p>Lite calls one external service: the public WordPress Vulnerability Database at wpvulnerability.net, to look up disclosed vulnerabilities for each installed plugin, theme, and your WordPress core version. No API key, no site URL, no admin email \u2014 only the slug being queried and a User-Agent identifying the plugin version. Each lookup is cached locally for 24 hours. See the \"External services\" section above for the full disclosure.<\/p>\n\n<p>The two-factor QR code is rendered locally in your browser; the TOTP secret never leaves your WordPress install.<\/p><\/dd>\n<dt id=\"will%20lite%20slow%20my%20site%20down%3F\"><h3>Will Lite slow my site down?<\/h3><\/dt>\n<dd><p>The scans run on cron (twice-daily CVE check, daily integrity scan). Runtime hardening is a handful of cheap filter hooks. No page-load impact you'll measure.<\/p><\/dd>\n<dt id=\"will%20lite%20break%20my%20site%3F\"><h3>Will Lite break my site?<\/h3><\/dt>\n<dd><p>The hardening checklist tells you what each fix does before you click it. Every one-click fix is reversible by editing wp-config.php or unchecking the option. Defaults are conservative \u2014 nothing is enforced site-wide on first install except the Operator gate, which only restricts Defender's own settings.<\/p><\/dd>\n<dt id=\"does%20it%20work%20alongside%20wordfence%20%2F%20ithemes%20%2F%20sucuri%3F\"><h3>Does it work alongside Wordfence \/ iThemes \/ Sucuri?<\/h3><\/dt>\n<dd><p>Technically yes, but running multiple security plugins is usually counterproductive \u2014 they fight over the same hooks. Run one, run it well.<\/p><\/dd>\n<dt id=\"is%20the%20audit%20log%20really%20tamper-evident%3F\"><h3>Is the audit log really tamper-evident?<\/h3><\/dt>\n<dd><p>Each row's row_hash is an HMAC-SHA-256 over the previous row's hash plus the row's own fields, keyed with a 32-byte chain key. The chain key is either (a) the <code>GDEF_LITE_AUDIT_KEY<\/code> constant in your <code>wp-config.php<\/code>, or (b) auto-generated and stored as a WordPress option on first use. An attacker with database write access can delete or modify a row, but cannot quietly recompute the following row's HMAC without the key \u2014 so the next row's stored hash will no longer match, and the break is visible from Settings \u2192 Operator \u2192 Chain status. For the strongest guarantee, set <code>GDEF_LITE_AUDIT_KEY<\/code> in <code>wp-config.php<\/code> so the key never lives in the database alongside the rows it signs.<\/p><\/dd>\n<dt id=\"how%20do%20i%20get%20the%20separate%20ghostables%20defender%20plugin%3F\"><h3>How do I get the separate Ghostables Defender plugin?<\/h3><\/dt>\n<dd><p>It's distributed from <a href=\"https:\/\/ghostables.io\">ghostables.io<\/a>. Install it alongside Defender Lite and Lite steps aside automatically; every setting you've configured here carries over. You never need it to keep using Defender Lite, which is free and fully functional on its own.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20uninstall%3F\"><h3>What happens if I uninstall?<\/h3><\/dt>\n<dd><p>Uninstalling (not just deactivating) drops Defender's three tables and clears its options. Your audit log goes with it. This is intentional \u2014 uninstall means uninstall.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.1.6<\/h4>\n\n<ul>\n<li>Fix: on the Scan page, the vulnerability and file-integrity scan progress modal could appear hidden behind its own backdrop. The modal is mounted on the page body \u2014 outside the plugin's styling scope \u2014 so its brand colour variables weren't resolving and the card rendered transparent. The modal now carries its own tokens and displays correctly. No change to scanning behaviour.<\/li>\n<\/ul>\n\n<h4>0.1.5<\/h4>\n\n<ul>\n<li>Authorisation: the integrity scan-control endpoints (start, tick, cancel) and the baseline and finding-resolve endpoints now enforce the Operator gate directly in their REST permission_callback \u2014 administrator capability plus an unlocked Operator session \u2014 because advancing a baseline rewrites the trusted file fingerprint (a security-state change). Read-only endpoints (CVE scan, scan status, audit verify) continue to require the administrator capability only. Locked requests return a clear, actionable 403.<\/li>\n<li>Removed remaining \"free tier \/ upgrade\" wording from the plugin header description to match the rest of the plugin: Defender Lite is free and fully functional, with the separate plugin described for information only.<\/li>\n<\/ul>\n\n<h4>0.1.4<\/h4>\n\n<ul>\n<li>Guidelines compliance. Audit-log retention is now a free, user-configurable setting (default 90 days, set to 0 to keep everything forever) \u2014 it is no longer presented as a paid limit. Nothing in the plugin is gated behind a licence, tier, quota, or time limit; every feature is free and fully functional.<\/li>\n<li>The \"More Security\" page now describes Ghostables Defender purely as a separate, more advanced plugin available from ghostables.io \u2014 no locked tiles, no \"unlock\", no in-plugin upsell or licence-key entry.<\/li>\n<li>All JavaScript and CSS is now loaded through wp_enqueue_*. The previous inline  and  blocks (the REST helper, scan modal, onboarding wizard) moved to enqueued assets\/js\/admin.js, assets\/js\/onboard.js, assets\/css\/onboard.css, and assets\/css\/login.css. Inline onclick handlers and inline style attributes were replaced with delegated event listeners and CSS classes.<\/li>\n<li>No change to the actual security features: vulnerability scanning, file integrity, hardening, two-factor authentication, Operator gate, and the tamper-evident audit log all work exactly as before.<\/li>\n<\/ul>\n\n<h4>0.1.3<\/h4>\n\n<ul>\n<li>Plugin Check round-2 cleanup. Fixed the only remaining ERROR (a $wpdb-&gt;prepare() call in the CVE scanner that concatenated time() into the SQL \u2014 now bound as %d), collapsed two multi-line $wpdb-&gt;prepare() calls onto single lines so the phpcs:ignore directive actually lands on the offending line, suppressed the PrefixAllGlobals sniff on view templates (they are require()'d inside controller methods, so their variables are method-local at runtime even though PHPCS sees them as global), and wrapped uninstall.php's body in an immediately-invoked closure so its working variables are genuinely function-scoped. No functional or behavioural changes.<\/li>\n<\/ul>\n\n<h4>0.1.2<\/h4>\n\n<ul>\n<li>Plugin Check cleanup: switched all filesystem operations to WP_Filesystem; sanitised every superglobal read with wp_unslash() + sanitize_text_field() \/ esc_url_raw(); annotated every deliberate direct $wpdb query with the rationale; prefixed all view-file local variables with gdef_ to satisfy the PrefixAllGlobals rule.<\/li>\n<li>No functional changes \u2014 all behaviour, option keys, DB schemas, REST routes, and admin UI are unchanged.<\/li>\n<\/ul>\n\n<h4>0.1.1<\/h4>\n\n<ul>\n<li>Vulnerability feed switched from Wordfence Intelligence to the public WordPress Vulnerability Database (wpvulnerability.net). Same coverage, GPL-compatible licensing, per-component 24h cache.<\/li>\n<li>Two-factor QR code is now rendered locally in the operator's browser using a bundled MIT-licensed library. The TOTP secret is no longer transmitted to a third party.<\/li>\n<li>Two-factor authentication now blocks XML-RPC and application-password channels for any user with 2FA enabled, closing the previous bypass.<\/li>\n<li>Two-factor recovery codes are stored as password_hash() values rather than plaintext.<\/li>\n<li>Brute-force throttle added to the Operator PIN, the Operator recovery code, and the 2FA challenge \u2014 5 failures in 5 minutes triggers a lockout with exponential backoff up to 1 hour.<\/li>\n<li>Audit chain upgraded from unkeyed SHA-256 to HMAC-SHA-256 with a chain key. The key is read from a <code>GDEF_LITE_AUDIT_KEY<\/code> wp-config constant when present, otherwise auto-generated and stored as an option. Existing pre-upgrade rows remain verifiable under the legacy scheme.<\/li>\n<li>The audit log no longer trusts <code>X-Forwarded-For<\/code> or <code>CF-Connecting-IP<\/code> headers by default \u2014 opt in via the <code>GDEF_LITE_TRUST_PROXY<\/code> wp-config constant or the <code>gdef_lite_trust_proxy<\/code> filter when the site genuinely sits behind a reverse proxy.<\/li>\n<li>Hardening: nginx server-block snippet for blocking PHP execution in \/uploads is now generated on the Hardening page (Apache .htaccess output unchanged).<\/li>\n<li>Admin pages no longer fetch Google Fonts from a CDN \u2014 system font stack is used instead.<\/li>\n<\/ul>\n\n<h4>0.1.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Active security for WordPress: vulnerability scanning, file integrity, hardening checklist, two-factor authentication, and a tamper-evident audit log.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/325268","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=325268"}],"author":[{"embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/ghostables"}],"wp:attachment":[{"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=325268"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=325268"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=325268"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=325268"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=325268"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/twd.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=325268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}