Hard Guard Security
Login protection, Audit Log, 2FA, Application Password controls, local antispam, GeoIP country access, file scanning, SSL diagnostics, hardening and recovery tools.
Important Safety Notice
Hard Guard Security provides tools intended to help website administrators improve and manage selected aspects of WordPress security. No security software can guarantee complete protection against every vulnerability, attack, configuration error, service interruption, compatibility problem, or data loss.
Before enabling or changing a security feature
- Create a complete backup of the WordPress database and website files.
- Verify that the backup can be restored successfully.
- Test important changes on a staging website whenever possible.
- Review the feature documentation and every warning displayed in the administration panel.
- Keep emergency access to the hosting control panel, filesystem, database, and WordPress configuration.
- Change one high-risk setting at a time and test the website, login page, administration area, REST API, scheduled tasks, and integrations after each change.
Features requiring particular care
Take additional precautions before changing the custom login URL, blocking the standard login endpoint, enforcing two-factor authentication, enabling an allow-only GeoIP policy, forcing HTTPS or HSTS, writing managed server rules, blocking XML-RPC or REST functionality, blocking PHP execution, quarantining files, resetting configuration, or deleting plugin data.
Scanner and quarantine limitations
Scanner results and security recommendations require administrator review. A detected file is not necessarily malicious, and a file that is not detected is not necessarily safe. False positives and false negatives are possible. Use quarantine before permanent deletion whenever available, and do not modify or remove a file unless you understand its role or have a verified restoration path.
Administrator responsibility
The website administrator is responsible for selecting, configuring, and operating enabled features; maintaining restorable backups; installing security updates; reviewing scanner findings; protecting recovery information; and confirming compatibility with the hosting environment, WordPress version, theme, plugins, caching layers, CDN, proxy, firewall, and external services.
Recovery
Before enabling access-control or authentication changes, generate and securely store the available emergency recovery information. If a configuration change prevents access, use the procedures in the Recovery section and the hosting control panel or filesystem access to disable the affected rule.
License, updates and support
Hard Guard Security is free and open source under the GPL-2.0-or-later license. All included features are available without payment, a license key, a trial period or a quota. Updates are distributed as new plugin releases. Voluntary donations do not unlock functionality.
1. Requirements
| WordPress | 7.0 or newer; tested through WordPress 7.1 |
|---|---|
| PHP | 7.4 or newer |
| Database | A database version supported by the installed WordPress release |
| Encryption | Sodium or OpenSSL is required for secure storage of TOTP, SMTP and Turnstile secrets |
| Optional services | Cloudflare Turnstile, an administrator-selected SMTP service, and country.is when GeoIP or Antispam country rules are enabled |
| Country lookup connectivity | Outbound HTTPS access to api.country.is is required only when an enabled country rule needs a lookup |
The scanner needs PHP read access to the WordPress files. Quarantine and managed server-rule features also need appropriate filesystem write access.
2. Installation
- Open Plugins → Add New → Upload Plugin.
- Download the latest Hard Guard Security release from GitHub and select the plugin ZIP.
- Choose Install Now, then Activate.
- Open Hard Guard Security → Settings.
- Hard Guard Security follows the WordPress locale selected for the current user. The plugin no longer has a separate interface-language selector and does not bundle compiled translation catalogs; WordPress.org language packs are loaded by WordPress when available.
- Global Hard Guard Security emails use the WordPress site language. User-specific 2FA messages use the recipient’s WordPress language.
- If you use Vulnerability Monitoring, note that automatic Hard Guard vulnerability-feed downloads are opt-in for new installations. Enable automatic updates explicitly or use the manual database refresh action.
Updating to 1.11.0 from 1.10.x
Version 1.11.0 introduces an explicit Client IP source. New installations default to Direct connection (REMOTE_ADDR). If an upgraded site already had Trusted proxy addresses configured, Hard Guard Security keeps the pre-1.11 behavior temporarily in Legacy automatic detection (not recommended) so existing proxy setups do not change silently. Open Settings → Networks and proxies, select the one header your proxy or CDN is configured to overwrite, verify the result in Proxy diagnostics, then leave Legacy automatic mode.
REMOTE_ADDR is an actual trusted proxy and that proxy is configured to replace or securely construct the selected header.Updating from older WP Guard / WP HARD GUARD builds
Version 1.10.35 uses the hard-guard-security directory, hard-guard-security.php main file and hard-guard-security text domain while preserving the existing wpguard_ options, user metadata, hooks and database tables for compatibility. The plugin detects older copies and legacy managed .htaccess marker blocks. Deactivate the older copy before activating Hard Guard Security, and do not run the older copy’s uninstaller with permanent data deletion enabled.
3. Recommended quick start
- Keep Direct connection (REMOTE_ADDR) unless WordPress is behind a reverse proxy, CDN or load balancer. If it is, add only the real proxy hops, select the exact client-IP header that proxy overwrites and verify the result in Proxy diagnostics.
- Before enabling GeoIP country access, confirm that WordPress resolves the real visitor IP, use Test country detection, review the country.is result and whitelist a trusted recovery IP/CIDR.
- Keep the default progressive login lockouts and test an allowed administrator IP.
- Configure and test email delivery before enabling email-based 2FA.
- Enable 2FA for your own account and store recovery codes outside WordPress.
- Generate an emergency recovery URL before hiding
wp-login.php. - Review Audit Log retention and enable only the alert rules you need.
- Run File Integrity and Quick Scan before using Full Scan.
- Enable HSTS only after HTTPS works correctly on the site and all required subdomains.
- Enable high-risk System Tweaks one at a time and test the complete site.
4. Login protection
Hard Guard Security counts failed authentication attempts by IP address, username, or a combined IP-and-username key. Optional IP-wide counting prevents attackers from bypassing limits by changing usernames. Login rate limiting also protects standard WooCommerce My Account login forms.
Progressive lockouts
Enter one to ten strictly increasing durations in minutes, for example:
5,30,1440
The first lockout lasts five minutes, the next thirty minutes and later lockouts one day. Values must be whole numbers between 1 and 525600.
Custom login URL
A change starts a five-minute safety test. Direct wp-login.php blocking remains disabled until the new URL is opened successfully. Login paths accept lowercase letters, numbers and single hyphens and cannot use reserved WordPress paths.
Cloudflare Turnstile setup
- Create or sign in to a Cloudflare account and open the Turnstile dashboard.
- Add a widget, enter a descriptive name, add the exact website hostname and use Managed mode as a safe starting point.
- Copy the generated Site key and Secret key to Hard Guard Security → Settings → Cloudflare Turnstile.
- Enable Turnstile, save the settings, sign out and test both the standard WordPress login and WooCommerce login in a private browser window.
Turnstile can be used without placing the website behind Cloudflare. The Site key is public, but the Secret key must not be included in source code, screenshots, support messages or configuration exports.
5. Networks and proxies
The whitelist, blacklist and trusted proxy fields accept only IPv4, IPv6 and CIDR ranges. Enter one value per line. Comma-separated input is normalized to one entry per line.
192.0.2.10 192.0.2.0/24 2001:db8::1 2001:db8::/32
ASN identifiers such as AS9141, hostnames and arbitrary text are rejected. CIDR entries are normalized to their network address.
Client IP source
Direct connection (REMOTE_ADDR) is the safest default and is used by every new installation. If WordPress receives requests directly from visitors, keep this setting.
If WordPress sits behind a trusted reverse proxy, CDN, load balancer or hosting gateway, choose exactly one source that the proxy is documented and configured to overwrite: X-Forwarded-For, X-Real-IP, Cloudflare CF-Connecting-IP, or RFC 7239 Forwarded. Forwarded headers are considered only when the direct REMOTE_ADDR matches Trusted proxy addresses.
Legacy automatic detection (not recommended) exists only for compatibility with upgraded pre-1.11 sites that already had trusted proxies configured. It tries multiple forwarded headers using the older behavior. Select an explicit source after verifying the proxy configuration.
Forwarded chains
For X-Forwarded-For and RFC 7239 Forwarded, Hard Guard Security walks the chain from the server side toward the visitor. It skips trusted proxy hops from the right and stops at the first untrusted address. When several proxies are used, every proxy or CDN hop that is allowed to append to the selected chain must be listed as trusted.
Malformed, incomplete or unsafe chains fall back to REMOTE_ADDR. Forwarded headers are limited to 4 KB and chains to 32 hops. RFC 7239 parsing accepts quoted IPv4/IPv6 for= values with optional ports.
Trusted proxy addresses
Enter only the addresses or CIDR ranges of the proxy, CDN, load balancer or hosting gateway that connects directly to WordPress or legitimately participates in the selected forwarding chain. Do not add visitor networks and never trust every address merely to make a forwarded header work.
Proxy diagnostics
The Settings page shows the current request’s REMOTE_ADDR, whether the direct peer is trusted, the configured source, the resolved visitor IP, what it was resolved from, any fallback reason, and the received CF-Connecting-IP, X-Real-IP, X-Forwarded-For and Forwarded values. These diagnostics are displayed locally to administrators and are not sent to the plugin author.
6. GeoIP country access
GeoIP country access is configured in Hard Guard Security → Settings. It applies a country policy to requests processed by WordPress across the site, including public pages, login, administration and API endpoints.
Policies
- Disabled: no country restriction.
- Block selected countries: listed recognized countries receive HTTP 403.
- Allow only selected countries: recognized countries outside the list receive HTTP 403.
Enter ISO 3166-1 alpha-2 codes, for example PL, DE, CZ. Invalid or empty lists are rejected while a policy is enabled.
Country source, caching and safe failure
Hard Guard Security uses only the https://api.country.is/{IP} API to resolve a visitor country. Cloudflare country headers, server GeoIP variables and local GeoIP databases are not used as the country source. The IP sent to country.is is the visitor IP resolved by the configured Client IP source; on a default direct installation this is REMOTE_ADDR, while a correctly configured proxy installation can resolve it from the explicitly selected trusted header.
Successful results are cached for 24 hours and failed lookups for 10 minutes. Loading or saving unrelated Settings does not initiate a lookup. Use Test country detection before enabling a policy and verify that the displayed IP and country are correct.
Blocked visitor page
The GeoIP settings can customize the HTTP 403 page title and message. Empty fields use translated defaults. The default English message is “Access to this website is unavailable from your location.”
An optional contact/help link can use https://, http:// or mailto:, with a custom link label. Custom title and message values are stored as plain text; HTML and scripts are removed. The HTTP 403 response code cannot be changed.
Exceptions and recovery
The existing IP/CIDR whitelist bypasses GeoIP blocking. Logged-in administrators, WP-Cron and WP-CLI are also allowed. When a country policy or related network settings are changed, the safety check evaluates the proposed Client IP source and Trusted proxy addresses before saving. A changed policy that would block the current recognized administrator country cannot be saved until the current IP/CIDR is whitelisted.
define('WPGUARD_DISABLE_GEOIP', true);
7. Audit Log
The Audit Log workspace contains Overview, Logins & IP blocks, Active Sessions, Live Traffic, Events, Alert Rules, Retention, Export and Settings.
The main Hard Guard Security Dashboard shows linked 24-hour security KPIs for failed logins, lockouts, unique blocked IP addresses and currently active IP lockouts. It also shows the 10 most recent Audit Log events. Selecting a KPI opens the relevant detailed Audit Log view, while selecting an event opens that record in Events.
Logins & IP blocks
This view summarizes authentication attacks and IP lockouts over 24 hours, 7 days or 30 days. It includes failed-login and lockout totals, unique blocked IP addresses, currently active IP lockouts, a trend chart and a ranking of the most active suspicious IP addresses.
The active-lockout table reflects the current rate-limiter state rather than only historical Audit Log entries. The Overview top-IP ranking is limited to suspicious authentication and blocking activity so ordinary successful requests do not inflate the list.
Active Sessions
Active Sessions is a read-only view of currently valid WordPress login sessions. Hard Guard reads the existing WordPress session metadata only when an authorized administrator opens this tab; it does not continuously scan sessions in the background.
The table shows the WordPress user, role, recorded IP address, browser/device summary, login time and expiration time. A valid session means the browser can remain authenticated until that session expires; it does not necessarily mean that the person is actively viewing the site at that exact moment.
Live Traffic
Live Traffic is an on-demand informational view of visitors currently browsing WordPress-rendered pages. Opening the tab starts a short-lived monitoring lease. While it remains active, newly rendered public pages can send a small browser heartbeat containing a temporary visitor identifier, the resolved IP address, logged-in WordPress identity when applicable, current page path, browser/device information and last-seen time.
Monitoring stops automatically shortly after the administrator leaves the tab. No permanent Live Traffic history is kept and the temporary visitor state is not added to Audit Log events. Sensitive query-parameter values such as passwords, tokens, nonces and API keys are redacted.
Events
Events include time, severity, action, actor, IP, object and result. Filters cover date, severity, user, IP, source, category, result and free-text search. Opening an event shows actor and target details, request path, HTTP method, Request ID and sanitized context.
Recorded WordPress activity
- Users, roles, administrator privileges and sessions
- Plugins, themes and WordPress Core changes
- Posts, pages and supported custom post types
- Optional comment lifecycle events
- Selected WordPress and Hard Guard Security security settings
Autosaves, revisions and full post/comment bodies are not stored. Sensitive context keys such as passwords, secrets, tokens, nonces, cookies and authorization headers are redacted.
Alert Rules
A rule can match an event or category, minimum severity and result. Threshold, time window, grouping and cooldown prevent excessive messages. Recipient fields accept valid email addresses only; an empty field uses the main Hard Guard Security notification recipients.
Retention and export
Retention can differ by severity. CSV and JSON exports use the active filters. Optional IP masking changes only exported files, not the stored event or the Events screen. Export and log-deletion actions are themselves audited.
| Maximum stored events | 1,000–1,000,000; default 100,000. When the cap is exceeded, the oldest normalized events are removed. |
|---|---|
| Retention by severity | 1–3,650 days for each level. Defaults: Critical 365, High 180, Medium 90, Low 30 and Info 30 days. |
| Displayed time zone | WordPress site time zone or UTC. Storage remains normalized; this setting changes the administration display. |
| Events per page | 25, 50, 100 or 200. |
8. Two-factor authentication
Users can choose email codes or RFC 6238 TOTP applications. Each user has independent configuration and ten one-time recovery codes. Administrators can review status, reset another user and require 2FA for selected roles with a grace period.
Configure a working mail transport before relying on email codes. TOTP secrets are stored encrypted when Sodium or OpenSSL is available. The QR code is rendered locally and the secret is not sent to a QR service.
| Email code validity | 3–15 minutes; default 5 minutes. Expired codes are rejected. |
|---|---|
| Maximum challenge attempts | 3–10; default 5. After the limit, the current challenge is invalidated and the user must sign in again. |
| Setup grace period | 0–30 days; default 7. Use 0 for immediate enforcement for selected required roles. |
Duplicate entry in Google Authenticator: If the same 2FA account appears twice, first confirm that both entries generate the same code. Then swipe the unnecessary entry to the left and use the delete option.
9. Application Passwords
Control access globally or by role, review a central inventory, revoke individual credentials or all credentials for one user and optionally revoke inactive credentials. Hard Guard Security logs creation, deletion, first use, new-IP use and failed authentication according to the configured notification policy.
WordPress displays a generated Application Password only once and stores a one-way hash. Hard Guard Security does not record plaintext credentials or hashes in logs or exports.
10. Scanner and file tools
File Integrity
The manual, read-only scan retrieves official WordPress.org checksums for the installed version and locale. It compares expected Core files located directly in the WordPress root and under wp-admin and wp-includes, reporting files whose hashes changed or whose official files are missing.
It also reports files not present in the official package when they are found directly in the WordPress root or under wp-admin or wp-includes, PHP-like executable files under uploads, and symbolic links in the WordPress root or Core directories. Symbolic links are reported but are not followed.
| ADDED | A file not present in the official WordPress package, found directly in the WordPress root, wp-admin or wp-includes. |
|---|---|
| MODIFIED | An expected Core file whose hash differs from the official WordPress.org checksum. |
| REMOVED | A file present in the official checksum list but absent from the installation. |
| UPLOADS SCRIPT | A PHP-like executable file under uploads that requires immediate review. |
| SYMLINK | A symbolic link in the WordPress root, wp-admin or wp-includes. The scan records it without following it. |
Core checksum and added-file checks exclude plugin files, theme files, language packs and directories other than wp-admin and wp-includes. The separate uploads check only searches for PHP-like executable files.
Excluded common root and configuration files are: .DS_Store, .htaccess, .user.ini, Thumbs.db, error_log, favicon.ico, license.txt, php.ini, readme.html, robots.txt, web.config, wp-config.php, wp-config-sample.php, plus .htaccess inside wp-admin and wp-includes.
For safety, each directory scan phase stops after 30,000 enumerated items and the report stores at most 400 findings. A report marked as truncated may not contain every issue.
Existing-file findings include file size and filesystem last-modified time. Hard Guard Security preserves the first-detected time while the same unresolved finding continues across later scans. The filesystem timestamp does not identify who changed a file and is not guaranteed to be its creation time.
File Permissions Scan
This read-only scan checks important WordPress paths and recursively reviews core, plugin and theme directories. World-writable paths are Critical. Group-writable paths and executable files are warnings because safe permissions depend on the server owner, group, PHP handler and deployment model.
Malware Scanner
Quick Scan focuses on recent and high-risk files. Full Scan checks the permitted WordPress tree in batches and can consume substantial CPU and disk I/O. Findings are heuristic and require human review. When Server Rules Protection is enabled, manual Quick and Full scans can also analyze suspicious .htaccess directives.
Database Malware Scanner
The optional Database Malware Scanner is available for manual Quick and Full scans and is read-only. Quick database scans inspect wp_options. Full database scans additionally inspect wp_posts.post_content and wp_postmeta.meta_value in bounded batches.
Detection uses context-aware behavioural rules for request-controlled PHP execution, decoder/eval chains, obfuscated external redirects, hidden external iframes, hidden-link SEO injection and confirmed encoded payloads. Conservative context handling is designed to avoid treating ordinary post/page code examples and common custom-code or analytics storage as malware solely because they contain code-like text.
Database findings are displayed separately from file findings and include severity summaries, scan-history counts and a dedicated JSON export section. Stored excerpts are escaped and known credentials or tokens are redacted. The scanner does not modify database records and does not require a remote database-malware signature database.
Vulnerabilities & updates
Full and Automatic scans run a separate Vulnerabilities & updates stage after file analysis. Hard Guard inventories the installed WordPress Core version, plugins and themes locally, including active/inactive status, and compares them against the currently verified signed Hard Guard threat-intelligence database.
Vulnerable means the installed version matches a known affected range in an advisory. Outdated means a newer version is available. A component can be both Vulnerable and Outdated; Hard Guard does not label an update as a vulnerability unless the installed version actually matches a known advisory range.
The signed feed can include a privacy-preserving current-version index for WordPress.org Core, plugins and themes. Outdated detection prefers that downloaded index and falls back to WordPress’ existing local update cache only when a component is not covered. Hard Guard does not force a new plugin/theme inventory request during the scan.
Vulnerability findings can include HGSA/CVE identifiers, CVSS score, Critical/High/Medium/Low severity, fixed version, known-exploited status, source attribution and advisory references. Separate vulnerability and outdated counts are included in scan status, history, JSON exports and completion notifications.
The vulnerability database is downloaded over HTTPS and verified with Ed25519 before use. Automatic updates run every 12 hours by default when enabled; administrators can disable automatic downloads and use Update vulnerability database now manually. The previous verified database is retained if a download, signature, schema or consistency check fails.
Scanner settings show database status, feed generation time, the site’s last successful database check and version-index status. A manual check distinguishes a newly downloaded feed from a successful check where the site already has the latest signed database. Failed scans expose stored database or consistency diagnostics instead of silently completing with mismatched counters.
Hard-Guard-Security/<version> User-Agent and does not include the website URL, installed plugin/theme inventory, installed versions, scan results, file paths or file contents. The feed server can still receive normal connection metadata such as the requesting IP address and request time.Scanner scheduling modes
MANUAL mode runs scans only when an administrator starts Quick Scan or Full Scan. AUTOMATIC mode schedules a Full Scan every configurable 1–365 days, with a default interval of 7 days. Manual Quick Scan and Full Scan remain available while automatic scheduling is enabled.
Automatic scans run in bounded WP-Cron batches and schedule continuation steps instead of relying on one long PHP request. A database advisory lock prevents overlapping automatic cron workers from processing the same scan concurrently. The Scanner shows the next planned automatic scan and warns when WordPress cron spawning is disabled.
Scan details, history, audit events and scanner notification emails identify whether a run was Manual or Automatic. Switching the Scanner back to MANUAL clears pending automatic cron jobs and safely stops an automatic scan that is in progress. Deactivation and uninstall clear both the automatic scanner start hook and continuation hooks.
Finding reasons are stored in a language-neutral form and translated when displayed. Hard Guard Security follows the current WordPress user locale, including when displaying compatible findings saved by earlier releases, without requiring another scan.
| Maximum file size for content analysis | 1–50 MB; default 5 MB. Files above the limit skip content signatures, but strong path-based checks such as PHP in uploads and double extensions still run. |
|---|---|
| Quick Scan recent-file period | 1–365 days; default 30 days. |
| Scan email alert | Optional. Send after a completed scan contains High or Critical findings, or Critical findings only. Global Email notifications and a working mail transport are required. |
Quarantine
Quarantine requires the current administrator password and moves the file into a protected non-executable location. It can break the website. Always keep a complete backup and verify a finding before quarantine or restore.
11. Antispam
Protects native WordPress comments, WooCommerce reviews using the native comment system and native registration. Optional integrations also protect the classic WooCommerce My Account registration and lost-password request forms. It combines a honeypot, signed timing token, JavaScript confirmation, optional Math CAPTCHA, per-IP rate limits, link limits, phrase rules, email-domain rules, local reputation, optional country rules and local heuristic language detection. WooCommerce checkout, checkout account creation and Store API registration are intentionally not intercepted.
Country filtering
Country detection uses only the country.is API. Only the resolved visitor IP address is sent; comment, review, registration and password-reset form content is not sent to country.is. Successful lookups are cached for 24 hours and failed lookups for 10 minutes.
- Add risk score for selected countries: adds the configured number of points and remains part of the normal scoring system.
- Allow only selected countries: directly rejects a protected submission from a recognized country outside the list.
- Block selected countries: directly rejects a protected submission from a recognized country on the list.
Strict allowlist and blocklist decisions cannot be cancelled by trusted-email score reductions or custom scoring thresholds. When country.is cannot determine a country, choose whether to allow the submission, moderate comments while blocking registrations, or block every protected submission.
Language filtering
Language detection is performed locally for comment text only. It is a heuristic for common Latin, Cyrillic, Arabic and CJK text, so short or ambiguous comments can be reported as unknown. Choose a direct action for a detected language outside the allowlist and a separate action for unknown language: allow, moderation, spam or immediate rejection where available.
Language decisions are direct and cannot be weakened by trusted-email score reductions. Language filtering applies to comment text only; registration and password-reset forms do not contain comment text and are not language-filtered.
Detection and list settings
Math CAPTCHA adds a small arithmetic challenge to protected interactive forms: native WordPress comments, WooCommerce reviews that use the native comment system, native registration, and enabled classic WooCommerce My Account registration and lost-password request forms. It does not apply to pingbacks, trackbacks, WooCommerce checkout or Store API flows. The default mode is Off.
- Off: no arithmetic challenge is shown.
- Always: every eligible protected interactive form requires the arithmetic challenge.
- Only for suspicious visitors: the challenge is shown when the resolved visitor IP has recent local spam/reject history or is close to the configured rate limit for that form type. Whitelisted IP addresses are excluded from this trigger.
Math challenges use addition, subtraction or multiplication. The challenge token is signed and time-limited, and the submitted answer is validated server-side. The expected answer is not exposed in HTML or JavaScript, and no external CAPTCHA service is contacted. Trusted logged-in users that are configured to bypass Antispam do not receive the challenge.
| WooCommerce My Account registration | Optional; default Off. Protects only the classic My Account registration form and shares the native registration per-IP limit. |
|---|---|
| WooCommerce lost-password requests | Optional; default Off. Protects only the classic My Account lost-password request form. |
| Math CAPTCHA | Off, Always, or Only for suspicious visitors; default Off. |
| Registration rate limit | Shared by native WordPress and protected WooCommerce My Account registration; default 2 submissions per IP / 60 minutes. |
| Password reset rate limit | Separate limit for protected WooCommerce lost-password requests; default 5 requests per IP / 60 minutes. |
| Minimum form completion time | 0–30 seconds; default 3. Use 0 to disable this timing signal. |
| Maximum links in a comment | 0–50; default 3. |
| Blocked phrases and wildcard patterns | One rule per line. Use plain text or * as a wildcard, for example cheap * pills. Lines beginning with # are comments. Arbitrary regular expressions are not executed. |
| Trusted email domains | Reduce risk for recognized domains. Enter domain names only, such as example.com. |
| Blocked email domains | Add a strong blocking score for configured domains. |
| Disposable email domains | Identify temporary mailbox providers maintained by the administrator. |
| Store a short content excerpt | Enabled by default. Disable it to reduce locally stored comment-content data in the Antispam quarantine. |
| Spam-wave alert | Disabled by default. The outbreak threshold accepts 10–10,000 incidents per hour; default 100. |
Validated structured fields
- Trusted email lists accept valid email addresses.
- Email-domain lists accept domain names without protocols, paths or wildcards.
- Country filters accept real ISO 3166-1 alpha-2 codes.
- Language lists accept two- or three-letter language codes with an optional region.
- Blocked phrases or wildcard lines are limited to 200 characters.
WooCommerce support is limited to the explicitly documented classic My Account forms and native comment-based product reviews. Checkout, checkout account creation and Store API registration are not intercepted. Other external form plugins such as Contact Form 7, WPForms, Elementor Forms, Fluent Forms and Gravity Forms are not intercepted generically. Test a dedicated integration before claiming coverage for a third-party form.
Statistics and digest emails
The seven-day statistics are populated only when the module checks a real protected comment, review, pingback, trackback, registration or protected WooCommerce lost-password request. Sending a digest does not generate sample records. Submissions from administrators and trusted logged-in users can be bypassed and are not counted. A clean submission may have no reason code, and country statistics appear only when country.is returns a valid country code.
The manual digest always covers the latest seven days and includes checked submissions, decisions, quarantine incidents, top reason codes and detected countries. The Antispam screen shows the current recipients and selected mail transport.
12. SSL and HTTPS
Check certificate health, choose a PHP or managed Apache/LiteSpeed redirect, inspect mixed content and scan live response headers.
HTTPS redirects
The PHP method redirects during WordPress execution. The managed .htaccess method is available only for Apache and LiteSpeed. Nginx does not read .htaccess; copy the displayed rule into the correct Nginx server block and test it manually.
.htaccess redirect when it detects a forwarded HTTPS request reaching the origin over HTTP.Security headers
Headers generated by PHP apply only to responses that execute WordPress. They do not automatically cover static files, web-server error pages, full-page server cache, or CDN responses served without PHP. Configure matching headers at the web server or CDN when complete response coverage is required.
- X-Content-Type-Options: sends
nosniffto reduce MIME-type confusion. - Referrer-Policy: supports
strict-origin-when-cross-origin,same-origin,strict-originandno-referrer. - X-Frame-Options: supports
SAMEORIGINorDENY.DENYcan break previews, page builders, checkout or embedded integrations. - X-XSS-Protection: the optional compatibility setting sends
0; the obsolete1; mode=blockbehavior is intentionally not used. - Permissions-Policy: controls camera, microphone, geolocation and payment features.
- X-Powered-By: can be removed when the PHP environment permits it.
The live scanner validates the returned values of HSTS, X-Content-Type-Options, Referrer-Policy, frame protection, CSP, Permissions-Policy, and the legacy XSS-filter header. It reports weak, malformed, duplicated, report-only, or limited policies instead of treating every present header as valid.
Content-Security-Policy: upgrade-insecure-requests only asks the browser to upgrade HTTP resource URLs. It is not a complete CSP because it does not restrict permitted script, style, image, frame, or connection sources. A report-only policy records violations but does not enforce blocking.
Permissions-Policy
Hard Guard Security can independently keep the browser default, block access everywhere, or allow the current origin for camera, microphone, geolocation and payment features. Camera, microphone and geolocation are prepared as blocked defaults when the feature is enabled; payment remains on the browser default to reduce the risk of breaking WooCommerce, Apple Pay, Google Pay or Payment Request API integrations.
After changing Permissions-Policy, test checkout, payment buttons, embedded content, video calls, maps and location-based forms. The live scanner reports an absent optional policy as OPTIONAL, an intentionally limited or broadly permissive policy as LIMITED, and malformed or duplicated rules as WARNING.
max-age=0 removes the stored HSTS policy only when the HSTS header is enabled and sent over HTTPS.13. System Tweaks
Includes sensitive-file protection, directory browsing prevention, file editor disabling, safe suppression of public PHP error display after WordPress loads, XML-RPC blocking, REST user endpoint protection, author enumeration protection and direct PHP-request controls.
Data hiding
Hide WordPress generator and discovery links removes selected public metadata, including the generator, RSD and Windows Live Writer links. This reduces casual information disclosure but does not conceal that the website uses WordPress.
Remove asset version query strings removes the ver parameter from public CSS and JavaScript URLs. This is mainly cosmetic and can make cache invalidation less predictable after an update, so leave it disabled when reliable cache busting is more important.
Disable public RSS and Atom feeds removes WordPress feed discovery links from the public page head and returns a 404 response for native feed requests, including main, category, tag, author, search and comment feeds. Leave this disabled when RSS readers, podcast clients or external integrations depend on WordPress feeds.
The error-display option turns off display_errors and display_startup_errors at runtime without disabling WP_DEBUG or error logging. Errors emitted before plugins load must still be controlled in wp-config.php, php.ini or the hosting panel.
Apache-compatible rules are stored in managed blocks and checked with loopback requests. A detected HTTP 5xx response restores the previous file. Nginx configuration remains a manual server-administrator task.
Server Rules Protection
Server Rules Integrity + Auto-Heal checks Hard Guard-managed .htaccess blocks on a daily WP-Cron schedule. If a managed block is changed or removed, Hard Guard can restore it and keeps the repair only after strict loopback verification succeeds; failed safety checks roll the change back.
Upload Directory Shield adds a dedicated PHP-like execution deny block to the WordPress uploads .htaccess on Apache/LiteSpeed while preserving unrelated existing content. A canary request verifies the rule and server errors trigger rollback.
The daily Suspicious .htaccess Scanner looks for dangerous PHP/CGI handlers, auto_prepend_file/auto_append_file directives and execution-enabling rules in upload, cache and temporary locations. It does not automatically delete foreign files. Current automatic findings appear under System Tweaks → Server Rules Protection with severity, file, line, detected rule and a redacted matched directive; Audit Log remains the historical event record.
14. Email notifications and SMTP
Use the standard WordPress mail transport or a dedicated SMTP configuration used only while Hard Guard Security sends its own messages. Test delivery before depending on alerts or email 2FA.
Hard Guard Security no longer has a separate Email language setting. Global security notifications, Scanner findings, Antispam reports, Audit Log alerts and test messages use the WordPress site language, including messages generated by WP-Cron. User-specific 2FA messages use the recipient’s WordPress language.
Recipient lists are validated. SMTP hosts accept a hostname, IPv4 or IPv6 address without a scheme or port. Password fields remain blank after save and retain the encrypted stored value unless a new password is entered.
From email must be a valid sender address accepted by the SMTP provider. From name is the human-readable sender shown next to that address. Some providers require the From email to match the authenticated mailbox or an explicitly verified sender identity.
Test and manual-digest actions report the destination address and whether the selected transport accepted the message. When WordPress or PHPMailer exposes an error, the administration notice and Audit Log include the diagnostic message. A successful wp_mail() result means that the local transport accepted the message; it does not guarantee final inbox delivery, so also check spam filtering and sender-domain DNS.
15. Multisite
Network activation creates the required tables and defaults for each site. Site-specific authentication and Audit Log data remain local to each site. Network Audit Log aggregates recent events from up to 100 sites.
Shared filesystem and server rules affect the complete network and can be changed only from the main site by a network administrator.
16. Privacy and stored data
No developer telemetry: Hard Guard Security does not send telemetry, usage statistics, scan results, website content or installed software inventory to the plugin author. When vulnerability-database updates are enabled, the plugin downloads a signed public feed from the Hard Guard website; the request does not contain the site URL, installed plugin/theme names or versions, scan results, file paths or file contents.
Local data: Security events may contain IP addresses, usernames, actor IDs, request paths and object identifiers. GeoIP blocks can store the resolved country code, country-data source and sanitized request path. Antispam may store an IP, email hash, email domain, score, reasons and an optional short excerpt. Scanner data may include file paths, hashes, metadata, database table/record identifiers, matched rules and short escaped excerpts. Database content is inspected only when an administrator explicitly enables Database Malware Scanner for a manual scan. File and database content are not uploaded to an external malware scanner.
Cloudflare Turnstile: Cloudflare receives Turnstile verification data only when Turnstile is enabled. Website administrators should review Cloudflare's Turnstile Privacy Addendum and reference it in their own privacy policy where required.
Email and SMTP: Hard Guard Security sends email through the SMTP server selected and configured by the website administrator. The SMTP password is stored encrypted in the local WordPress database when Sodium or OpenSSL is available.
Country lookup: Site-wide GeoIP access control and Antispam country rules use only country.is. When one of these features needs a country value, the resolved visitor IP address is sent to https://api.country.is/. Comment, registration and scanned-file content is not included. Successful results are cached for 24 hours and failures for 10 minutes. Unrelated Settings pages and saves do not initiate lookups. Site-wide GeoIP fails open when the country is unavailable; Antispam uses the failure action selected by the administrator.
Hard Guard vulnerability intelligence: When enabled, automatic updates periodically request the signed compressed database from https://cve.wp-hard-guard.ma7.eu/vulnerabilities-v1.json.gz and its detached signature. Matching against installed software is local. The feed server can receive normal HTTPS connection metadata such as the requesting IP address and request time, but the request does not send the site URL, inventory, installed versions, scan results, file paths or file contents.
Personal-data tools: Hard Guard Security integrates with WordPress Tools → Export Personal Data and Tools → Erase Personal Data. Erasure removes matching user-specific metadata, antispam and lockout records and anonymizes matching Audit Log events so non-personal security metadata can be retained.
PayPal donations: The optional Donate link opens PayPal only after an administrator clicks it. No PayPal scripts, images or tracking pixels are loaded on Hard Guard Security screens before that action.
Uninstall cleanup: When the explicit permanent cleanup option is enabled, uninstall removes Hard Guard Security options, transients, user metadata including 2FA data, all plugin tables, logs and safely validated Scanner quarantine files. In Multisite, the main-site preference is applied across the network. Deactivation alone does not delete stored data.
17. Emergency recovery
Add only the required temporary constant to wp-config.php before the “stop editing” comment:
define('WPGUARD_DISABLE_LOGIN_HIDING', true);
define('WPGUARD_DISABLE_2FA', true);
define('WPGUARD_DISABLE_RATE_LIMITING', true);
define('WPGUARD_DISABLE_HTTPS_REDIRECT', true);
define('WPGUARD_DISABLE_GEOIP', true);
Remove the constant immediately after access is restored and the underlying configuration is corrected. A single-use recovery URL can also be generated from the Tools screen and should be stored securely.
18. Troubleshooting
An IP whitelist entry does not work
Use an IP or CIDR, not an ASN or hostname. Behind a proxy, add only the real proxy address/range to Trusted proxy addresses, select the exact Client IP source that proxy overwrites, and confirm the resolved visitor IP in Proxy diagnostics.
Email codes or alerts do not arrive
Run the test email, verify the host, port, encryption, credentials and sender, then inspect mail-server logs and spam filtering.
A scan appears stuck
Reload the Scanner screen. Running scans are recovered from the database. Check PHP execution time, memory, file permissions and web-server/PHP logs.
An Audit Log alert does not fire
Verify the rule is enabled, the event matches every filter, the threshold occurs inside the time window and the grouping key is correct. Cooldown can suppress repeated alerts.
GeoIP blocks the wrong visitors or has no effect
Use Proxy diagnostics first and confirm the resolved visitor IP is correct. If a proxy or CDN is used, configure only its real IP/CIDR ranges as trusted proxies and select the exact header it overwrites. Then use Test country detection and verify that the server can make outbound HTTPS requests to api.country.is. Successful results can remain cached for 24 hours and failed lookups for 10 minutes. Site-wide GeoIP allows requests when the country is unavailable; Antispam follows its configured unknown-country action. Full-page CDN/server cache and static files can be returned before WordPress executes a site-wide rule.
Settings are rejected
The message identifies invalid structured entries. The previous working configuration is kept. Correct the listed IP/CIDR, email, domain, country, language, lockout, login-path or SMTP value and save again.
19. Updates, backup and plugin uninstallation
Create a database and filesystem backup before every security-plugin update. Test updates on staging, especially when server rules, login hiding or Multisite are enabled.
Deactivation: clears the daily Hard Guard Security cron hook and removes managed server rules where the configuration file is writable, but keeps settings, user data, logs, tables and quarantine files.
Uninstall without permanent cleanup: removes runtime artifacts and plugin capabilities but retains stored settings and data so the plugin can be installed again.
Uninstall with permanent cleanup enabled: permanently removes all eight Hard Guard Security database tables, all options and transients using the plugin prefix, all user metadata using the plugin prefix including 2FA data, network metadata, logs, scan records and safely validated Scanner quarantine files. Standard empty quarantine directories and plugin-created protection files are also removed. In Multisite, the main-site cleanup preference is applied to every site.
If an Apache-compatible .htaccess file is not writable, managed rules cannot be removed automatically and the uninstall process writes a diagnostic message to the server error log. Remove any remaining Hard Guard Security block manually.
Settings export and import
Export creates a JSON file containing the plugin configuration and package version. The Turnstile Secret key and SMTP password are blanked before download. Authenticator secrets and recovery codes are user metadata and are not part of the settings export.
Import accepts a non-empty Hard Guard Security JSON file up to 1 MB and validates all supported values before saving. If validation fails, the existing configuration remains active.
For safety, import preserves the destination site’s stored Turnstile Secret key and SMTP password, disables direct wp-login.php blocking and does not activate server-level System Tweaks. Re-enter or verify all secrets, review proxy and GeoIP rules, test the custom login path and mail delivery, and enable high-risk protections manually.
20. Support
| Contact email | contact@wp-hard-guard.ma7.eu |
|---|---|
| Response time | Best effort; no guaranteed response time is stated for the free open-source edition. |
What support includes
- Installation and basic configuration guidance.
- Help diagnosing confirmed Hard Guard Security errors and compatibility problems.
- Clarification of documented features and settings.
- Bug reports and maintenance feedback for current plugin releases.
Support does not include custom development, website repair, malware removal, server administration, third-party plugin customization or emergency incident response.
When contacting support, include the Hard Guard Security version, WordPress version, PHP version, a clear description of the issue and any relevant error message. Do not send passwords, recovery codes, API secrets or other confidential credentials.
21. Credits and licenses
Hard Guard Security is licensed under GPL-2.0-or-later. The bundled local QR renderer includes work based on qrcode-terminal and QRCode for JavaScript. Its notices and Apache/MIT license texts are included under assets/vendor/wpguard-qr/.
Cloudflare Turnstile is an optional external service and is not bundled software. No premium runtime services are required by the plugin.
Author: Andrzej Kupis