Home › Docs › Security Guard user guide

Security Guard user guide

Updated October 20, 2026

On this page What do I need? How do I install it? What should I do first? How do I run a scan? What does the scan check? What do the severity levels mean? How do I hide a false positive? How does the baseline work? What does the Protection tab do? How do I switch the policy to Enforce safely? What does the Event log record? How does the licence work? What happens to my data when I delete the plugin? Can I run it from the command line? What should I do if the scan finds malware? What does it store, and what leaves my site? What changes on Nginx? Something isn't working. What should I check? What doesn't it do?

Security Guard scans your WordPress files, database and users for injected scripts, web shells and rogue administrators, removes known injected scripts from the pages your visitors receive, and logs what changes. This guide walks through every tab of version 1.0.1, from the first scan to cleaning up. The screenshots come from our test site, where we planted harmless copies of attack code so the screens show real findings.

What do I need?

  • WordPress 6.0 or newer and PHP 8.0 or newer. No other plugin is needed.
  • An administrator account with the manage_options capability.
  • Apache, LiteSpeed or IIS hosting for the deny rules the plugin writes itself. On Nginx, see the Nginx section.

A developer can let another role open the Scan, Baseline, Protection and Event log tabs with the psr_security_guard_capability filter. The License and Data tabs stay at manage_options whatever the filter returns. Anyone the filter lets in can change the alert address and the allowed hosts, ignore findings, save a new baseline and clear the log, so give it only to people you would trust as administrators.

Multisite, Nginx and sites with more than about 12,000 files have not been tested yet.

How do I install it?

  1. Download the ZIP from My Licences, then go to Plugins → Add New → Upload Plugin and upload it.
  2. Click Activate. The plugin saves its default settings, adds the no-PHP rule to uploads/.htaccess and schedules the daily scan.
  3. Open Settings → Security Guard. It has six tabs: Scan, Baseline, Protection, Event log, License and Data.
  4. Paste your licence key on the License tab so the site receives updates. Every feature works without a key.

Installing an add-on and activating your licence has the same steps with screenshots of the store side.

Updating from 1.0.0 moves your saved baseline into the new private folder and deletes the old uploads/psr-security-guard/ folder with everything in it. Your settings, ignore list and event log stay as they were. Save a new baseline once after updating: 1.0.1 checks more files than 1.0.0 did, such as every PHP file in the WordPress root, so the first scan lists those files as added until you do.

What should I do first?

  1. Run a full scan on the Scan tab.
  2. Read the findings, High first, then Medium. Ignore anything you have checked and know to be harmless.
  3. Save a baseline on the Baseline tab once the site is clean.
  4. Leave the script filter and hardening on, and run the Content-Security-Policy in Report only mode for a few days.
  5. Read the Event log, add the hosts your site really uses, then switch the policy to Enforce.

How do I run a scan?

Open the Scan tab and click Run full scan. The status line moves through Collecting files…, Scanning files 120 / 11516 and so on, then Checking the database, users and WordPress core…. Leave the page open. When it ends, the page reloads with the result.

Security Guard Scan tab: run a full scan and read each finding with its file, line and rule
The Scan tab after a full scan of our test site. Each finding shows where it is, the rule it matched and the text around the match.

The scan is read-only. Each request checks up to 120 files or runs for about 10 seconds, whichever comes first, and the next request carries on, so it doesn’t run into a server time limit. On our development machine 11,516 files took about six minutes.

The Last scan card shows the date, the number of files checked and three counts: High, Medium and Low / info. The table below it has these columns:

  • Severity. HIGH, MEDIUM, LOW or INFO.
  • Where. A file and line, a post (Post #12 (post) “Home”), a post meta key, an option name, or an administrator.
  • Finding. What matched, with the rule name under it, such as ETH_CALL_STRING.
  • Detail. The text around the match, so you can judge it without opening the file.
  • Ignore. Hides that finding from now on.

The table shows the first 400 findings, High first. After a scan with High findings, a red notice also appears at the top of other admin screens with a Review it link.

A rescan clears once the site is clean. Version 1.0.1 leaves the plugin’s own stored results and temporary values out of the database check, so the matched text it saved last time is not reported again as a new finding.

What does the scan check?

It checks code files, uploads, the database, administrators, plugins and WordPress core, plus every change since your baseline.

  • Code files anywhere in wp-content outside uploads, which takes in plugins, themes, must-use plugins and drop-ins, and every PHP file in the WordPress root folder (wp-config.php among them), plus the root .htaccess and .user.ini. It looks for blockchain RPC calls and endpoints, Web3 providers, clipboard scripts that carry a shell command, fake verification text that asks for a paste, eval of decoded data, obfuscated strings, web shells and auto_prepend_file directives. Code files over 2 MB are skipped. An .htaccess or .user.ini is never skipped for size: it is read in full, up to the oversized limit below.
  • Server config files. Every .htaccess and .user.ini the scan reaches is read line by line, the ones in uploads too. A line that makes other files run as PHP is Medium: AddHandler, AddType, SetHandler or ForceType with php in it, or a RewriteRule whose H= or T= flag names php. An auto_prepend_file or auto_append_file line is High. Letter case makes no difference, and an .htaccess line split with a backslash is joined first, as Apache joins it. AddHandler cgi-script is a hardening line, so it is left alone. Each finding names its line number. A file too large to check in full (past 32 MB, or 5 seconds of reading) gets a Medium finding called Oversized server config file, so you can read the rest by hand.
  • Uploads. Any PHP file is High, unless it is an empty placeholder such as an index.php that only says “Silence is golden”. Images that contain PHP code are High, and SVG files with a script are Medium.
  • The database. Posts, post meta and options are searched for the same injected-script patterns.
  • Administrators. Every administrator is listed as Info. One created in the last 30 days is Medium.
  • Plugins. A plugin listed as active whose file is missing is Medium. Every must-use plugin and drop-in is listed as Info.
  • WordPress core. With Verify WordPress core files on, each core file is compared with the official checksum WordPress.org publishes for your version. A changed file is High. An extra PHP file in wp-admin or wp-includes is High only if its content matches a pattern; otherwise one Low line lists them as likely leftovers from an older version.
  • Changes since the baseline, once you have saved one.

The scan skips only a short list of folders: wp-content/cache, wp-content/upgrade, wp-content/upgrade-temp-backup and wp-content/ai1wm-backups by exact path, the plugin’s own folder, and any folder named .git or node_modules. A folder called cache inside a plugin is still scanned, because that is a place attackers hide files.

What do the severity levels mean?

High means look at it today, Medium means confirm it, Low is probably harmless and Info is a fact to review.

LevelMeaningExamples
HighLook at it today.A known malware pattern, an auto_prepend_file line, a changed core file, PHP in uploads, or a new administrator or must-use plugin since the baseline.
MediumWorth confirming.An obfuscation pattern such as String.fromCharCode or atob, an administrator created in the last 30 days, or a code file added or changed since the baseline. In .htaccess or .user.ini, a PHP handler line or a file too large to check in full.
LowProbably harmless, shown so nothing is hidden.Leftover core files with no malware pattern.
InfoA fact to review.The administrator list, must-use plugins, drop-ins, or No baseline saved yet.

A High finding is a reason to look, not proof of an infection. Another security plugin’s signature list, for example, contains the same words this one searches for.

How do I hide a false positive?

Click Ignore on the row. The finding disappears and the notice says Finding hidden. It will not be reported again.

The match is by place and rule, so a new problem of the same kind in the same file stays hidden too. Only ignore what you have checked.

To hide a whole folder, such as a plugin’s vendor folder, add a line to Ignore paths on the Protection tab. Any finding whose location contains that text is left out of the result.

There is no button to bring an ignored finding back in 1.0.1. A developer can clear the whole list with wp option delete psr_security_guard_ignore.

How does the baseline work?

A baseline is a record of the site while it is clean. Click Save / update baseline now on the Baseline tab. The plugin stores a fingerprint of every code file in wp-content outside uploads, which covers your plugins, themes, must-use plugins and drop-ins. It adds every PHP file in the WordPress root, the root .htaccess and .user.ini, and wp-config.php, even when that sits one folder above the root. Media and archives are left out. It also records the list of administrators and must-use plugins.

The tab then shows the date of the current baseline and its totals. On our development machine that was 11,377 code files and 5 administrators.

Security Guard Baseline tab: a saved baseline of 5,760 files and 1 administrator
The Baseline tab with a saved baseline, showing its date, the number of code files and the number of administrators.

From then on every scan adds:

  • Code file added since baseline (Medium), for new PHP and JavaScript files.
  • Code file changed since baseline (Medium), for any file whose content changed.
  • Must-use plugin added after baseline (High).
  • Administrator account that did not exist at baseline (High).

This is what catches a backdoor that matches no known pattern. Save the baseline again after you update plugins or themes, or the next scan flags every updated file. The list stops at about 400 changed files per scan.

What does the Protection tab do?

It holds four cards of settings: Front-end protection, Content-Security-Policy, Hardening, and Scanning and alerts. Click Save settings at the bottom after any change. Settings take effect on the next page load, so purge your page cache afterwards if you use one.

Security Guard Protection tab: the script filter and the Content-Security-Policy in report-only mode
The Front-end protection and Content-Security-Policy cards, with example hosts typed in and the policy in Report only.

Front-end protection

  • Remove injected scripts (on). Checks every inline script in a front-end page against the EtherHiding, ClickFix and obfuscated-loader rules. A match is replaced with an HTML comment and logged as High. It never runs in wp-admin, AJAX, cron, REST requests, feeds, the Customizer or the Elementor, Bricks and Divi builders.
  • Strict script allow-list (off). Also removes external script tags whose host is not listed below. Your own domain is always allowed. Turn it on only after checking that the site still works.
  • Allowed script hosts (empty). One host per line or separated by commas, such as cdn.example.com. A leading *. covers subdomains. These hosts are also added to the CSP script-src.

On 20 October 2026 we planted an EtherHiding-style loader and a ClickFix clipboard script in a test site. With the filter on, both came out of the page and each left a High line in the event log; the theme’s own scripts stayed. Our guide to the fake Cloudflare CAPTCHA and ClickFix attack shows what those scripts do to a visitor.

A script counts as external only when it has a real src attribute. A script with only data-src or a similar attribute is treated as inline, so its code is checked. Data blocks such as JSON-LD structured data, import maps and speculation rules are left alone.

The filter doesn’t skip a page silently. When a page is too large or malformed to check in one pass, it checks the scripts one by one. If a script still can’t be checked, it stays in the page and the Event log gets a Medium line, at most once an hour for each page address.

Content-Security-Policy

  • Mode (Report only (recommended first)). The other choices are Off and Enforce. In Report only the browser blocks nothing and reports what it would have blocked. In Enforce the browser blocks it.
  • Allowed connect hosts (empty). Hosts that page scripts may call with fetch, XHR or WebSocket, such as stats.example.com. This is the setting that stops an injected loader reaching a blockchain RPC endpoint.
  • Allowed frame hosts (empty). Hosts you embed in iframes, such as a video or maps service.
  • Send security headers (on). Sends X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN and Referrer-Policy: strict-origin-when-cross-origin.

The policy keeps scripts to your own site plus the listed hosts, and still allows inline scripts so themes keep working. Images, styles and fonts may load from any HTTPS address. On 20 October 2026 our test site, still on the default settings, answered with a Content-Security-Policy-Report-Only header and connect-src ‘self’. Nothing was blocked until we chose Enforce.

Security Guard hardening settings: file editor off, PHP blocked in uploads, user names hidden, XML-RPC off
The Hardening and Scanning and alerts cards. Every hardening switch is on by default, and e-mail alerts are off.

Hardening

  • Disable the theme and plugin file editor (on). Someone with a stolen dashboard login cannot edit PHP from wp-admin.
  • Block PHP execution in uploads (on). Writes a block that starts with # BEGIN Security Guard (psr-security-guard) in uploads/.htaccess and keeps any rules already in the file. It refuses .php, .PHP, .php5, .phtml, .phar and .pht files, and double extensions such as photo.php.jpg. Turning it off or deactivating the plugin removes the whole block, markers included.
  • Hide user names from visitors (on). For logged-out visitors it closes the REST user list (including the ?rest_route= form), every ?author= lookup, /author/name/ archives (they return 404), the users sitemap, and the author name and link in oEmbed data. User ID numbers inside REST post data stay as WordPress sends them.
  • Disable XML-RPC (on). Turns off XML-RPC logins and pingbacks, and removes the X-Pingback header and the RSD link from your pages. Apps and services that still connect over XML-RPC stop working while this is on.
  • Generic login error message (on). A wrong user name or password both show The username or password is incorrect. The lost-password form gives the same answer whether or not the account exists.

We widened Hide user names after testing 1.0.0 on 20 October 2026: the REST list and ?author=1 were closed, but /author/admin/ and the users sitemap still showed the administrator’s user name. Version 1.0.1 covers both.

Scanning and alerts

  • Verify WordPress core files (on). Compares core files with the official checksums.
  • Scan every day (on). The first daily scan runs about an hour after activation. It works through WP-Cron in steps, and one step takes up to about 10 seconds.
  • E-mail alerts (off) and Alert e-mail. Sends medium and high events to the address you enter. You can’t switch alerts on without a valid address: Save settings shows an error instead. The same alert is sent at most once every 30 minutes.
  • Ignore paths (empty). One path fragment per line, for example wp-content/plugins/some-plugin/vendor/.

Alerts need working mail on your server. We haven’t tested delivery on a real mail server yet, so send yourself a test from another plugin or your host first.

How do I switch the policy to Enforce safely?

Run Report only for a few days, add the hosts your site really uses, then choose Enforce.

  1. Leave Mode on Report only and browse your site for a few days, including checkout, forms and any page with video or maps.
  2. Open the Event log and look for lines that start with CSP. Each names the blocked address, the rule and the page.
  3. Add the hosts you recognise, such as your analytics or payment provider, to Allowed connect hosts, Allowed script hosts or Allowed frame hosts.
  4. When no new CSP lines appear for your own services, set Mode to Enforce and click Save settings.

CSP reports are logged quietly at Info and never sent by e-mail. Repeats of the same blocked host within 10 minutes share one line, and the whole site logs at most about 60 reports per 10 minutes, so a busy page can’t flood the log. With Mode set to Off, the plugin doesn’t accept reports at all.

Enforce can break a page that loads scripts or frames from other hosts, or calls other services from the browser, until you add those hosts. Use only one plugin that sends a Content-Security-Policy header. If another plugin or your host already sends one, set Mode to Off here.

What does the Event log record?

The Event log tab lists the newest 200 events with their time and severity. Clear log empties it.

Security Guard event log: a new administrator, failed logins and a removed injected script, each with time and severity
The Event log after our test: a new administrator, failed logins and a removed injected script, each with its time and severity.
  • New administrator accounts and users promoted to administrator, with who did it (High).
  • A new must-use plugin file that isn’t in the baseline, checked when someone opens wp-admin, at most every six hours (High).
  • Injected inline scripts removed from a page, with the rule and the page address (High). The same rule on the same page is logged once an hour with a count of repeats.
  • External scripts removed by the strict allow-list (Medium).
  • Scripts the filter couldn’t check (Medium), at most once an hour per page.
  • 10 failed logins in 10 minutes from one IP address, with the last user name tried (Medium).
  • CSP violations (Info).
  • Administrator logins with the IP address, plugins activated or deactivated, theme switches, saved baselines and scan results (Info, or High when a scan found High items).

How does the licence work?

Paste the key from your purchase receipt into License key on the License tab and click Activate. The Status badge turns to Active, and the card shows when the licence expires and when it was last verified. Re-check Now asks the licence server again, and Deactivate frees this site’s slot so you can use the key elsewhere.

Security Guard License tab: paste the key from your receipt and activate
The License tab before a key is entered. Paste the key from your receipt and click Activate.

The site checks in once every 24 hours. Every feature keeps working whatever the licence status; the key only brings automatic updates and support. Licences cover 1, 5 or unlimited sites, and the price of each is on the Security Guard page.

What happens to my data when I delete the plugin?

By default it is kept, so reinstalling brings back your settings, baseline and log. Deactivating never deletes data.

Security Guard Data tab: plugin data is kept on delete unless you tick the box
The Data tab. Delete all data when the plugin is deleted is unticked, which is the default.

To remove everything, tick Delete all data when the plugin is deleted on the Data tab and click Save Settings. The same choice appears in a popup when you deactivate the plugin, with Keep my data as the other option.

With the box ticked, deleting the plugin removes the settings, the saved baseline, the last scan result, the event log, the ignore list, the plugin’s temporary values and its private folder in uploads. The licence key is removed on delete either way.

Can I run it from the command line?

Yes, with WP-CLI. Three commands are available:

wp security-guard scan --min=medium --format=table
wp security-guard baseline
wp security-guard log --number=20
  • scan runs a full scan in one go and prints a summary in the form 11516 files checked. High: 5, medium: 4, low/info: 10, then the findings. --min sets the lowest level shown (high, medium, low or info, default low) and --format takes table or json. It exits with code 1 when anything High is found, so a deploy script can stop.
  • baseline saves a baseline and reports how many files it recorded.
  • log prints the latest events, 20 unless you pass --number.

A value the command doesn’t know, such as --format=csv, stops it with an error instead of falling back to the default.

What should I do if the scan finds malware?

Back up, replace or clean every High finding, lock the accounts down, then rescan until nothing High remains. Security Guard reports; it never deletes or edits a file it flags. Work through it in this order:

  1. Take a full backup of files and database first, so you can undo a mistake.
  2. Open each High finding. Replace an infected plugin or theme with a fresh copy from its official source, and remove PHP files from uploads that shouldn’t be there.
  3. Remove injected code from the posts, post meta and options the scan lists by number or name.
  4. Delete administrator accounts you don’t recognise and change every administrator password.
  5. Change the keys and salts in wp-config.php, then the database and hosting passwords.
  6. Run the scan again until nothing High remains, save a fresh baseline and switch the policy to Enforce.

If you aren’t sure whether code is yours, compare the file with a fresh download of the same version before you change it. Our guide on how to check if a WordPress site is hacked covers the signs to look for beyond the scan.

What does it store, and what leaves my site?

Everything stays on your site except the core checksum download and, once you enter a key, the licence and update checks.

  • Settings, the last scan result, the event log, the ignore list and the daily-scan state are stored as WordPress options. It adds no database tables.
  • The baseline sits in a private folder in uploads with a random name made for your site, psr-security-guard- followed by 24 letters and numbers. The folder holds an index.php, a deny-all .htaccess for Apache and LiteSpeed, and a web.config for IIS.
  • A scan’s temporary work files are deleted when it finishes, fails or expires. Scan and baseline files store administrators by user ID, never by e-mail address; the login and e-mail are looked up when you open the admin screen.
  • The event log can contain administrator user names, e-mail addresses and IP addresses. It stays on your site and Clear log removes it.
  • Your files and database are never uploaded. The core check downloads checksums through WordPress’s own get_core_checksums() function (checked 20 October 2026), and you can switch it off. The licence and update checks send only your key and site address to pluginsprout.com.
  • It loads no external scripts, fonts or analytics.

What changes on Nginx?

Nginx ignores .htaccess files, so two protections need a rule from you or your host: no PHP in uploads, and no web access to the private folder. The WordPress Nginx guide (checked 20 October 2026) confirms Nginx has no .htaccess support.

The folder’s random name can’t be guessed from outside, but a rule closes it anyway. Rules like these do both. Place them above your PHP location block.

location ^~ /wp-content/uploads/psr-security-guard- { deny all; }
location ~* ^/wp-content/uploads/.*\.(php\d?|phtml|phar|pht)(\.|$) { deny all; }

We haven’t tested Security Guard on Nginx yet, so check that a PHP file in uploads returns 403 after you add them.

Something isn’t working. What should I check?

Find what you see in the left column; the right column says what to do.

What you seeWhat to do
The scan stopped: and an errorA request timed out or a server rule blocked admin-ajax.php. Click Run full scan again. If it repeats, run wp security-guard scan or ask your host to check the error log.
High findings stay after you cleaned upClick Run full scan again; 1.0.1 doesn’t report its own stored results. If a row remains, the code is still in that file, post or option, or in a cached copy. Check the Where column.
High findings in another copy of Security Guard or in another security pluginSignature lists contain the words they search for. The plugin skips only its own installed folder. Delete old copies, or Ignore the rows once checked.
Many Code file changed since baseline rows after an updateThe baseline is older than the update. Check the files belong to the plugins you updated, then save the baseline again.
Saving the baseline ends in an error on a large siteThe baseline is saved in one request. Run wp security-guard baseline instead.
A video, map or analytics stopped after EnforceAdd its host to Allowed connect hosts, Allowed frame hosts or Allowed script hosts, or set Mode back to Report only.
A script you added is missing from the pageLook in the Event log for Removed an injected inline script or Removed external script from non-allowed host. Add the host to Allowed script hosts, or turn off Strict script allow-list.
A Medium line says the filter couldn’t check a pageA script on that page was too large or malformed to check, so it was left in place. Open the page source and look at its biggest inline scripts, then run a full scan.
Theme File Editor and Plugin File Editor have goneDisable the theme and plugin file editor is on. Untick it while you edit, then tick it again.
Save settings shows an error about the alert addressE-mail alerts is ticked but Alert e-mail is empty or not a valid address. Enter a working address and save again.
No alert e-mailsTick E-mail alerts, enter an Alert e-mail and save. Check that your site can send mail. Repeats of the same alert are held back for 30 minutes, and CSP reports are never mailed.
The daily scan didn’t runWP-Cron only runs when the site gets a visit, as the WordPress cron documentation (checked 20 October 2026) explains. On a quiet site, or with DISABLE_WP_CRON set, add a real server cron job.
PHP still runs in uploadsYour server ignores .htaccess. See the Nginx section.

What doesn’t it do?

It is not a firewall and has no live threat feed, so it cannot stop an attack before it reaches WordPress. It finds and contains what it can see on the site.

It never cleans up by itself. That is on purpose: it can’t break a site by deleting something that only looked suspicious. It has no two-factor login, login limiting or vulnerability database.

It matches known patterns. A loader written a new way may not match until the signature list is updated, which is why the baseline and the daily scan exist.

It can’t see an administrator that malware hides from the user list with a pre_user_query filter. If you suspect one, compare the Users screen with the wp_users table through your host’s database tool.

If you need a firewall or automatic cleanup, read our comparison of WordPress malware scanners before you choose. Keep updates, strong passwords and off-site backups going too. A security plugin is one layer.

Still stuck? Email support@pluginsprout.com We reply within 24 hours, Monday to Friday.