How ShieldWave works, and how to check it

A security plugin asks for a lot of trust: it reads every file on your site. This page states what Ensomedia Security does, what it never does and exactly what leaves your server, with a way to verify the parts you should not have to take on faith.

Describes plugin 1.1.30. Where an older version differs, the text says so. Updated 12 November 2026.

What runs on your site

The checks run inside WordPress, on your own server: malware analysis of files that WordPress.org cannot vouch for, file integrity, file changes against a recorded baseline, uploads, injected content, exposed files, accounts and configuration. Scans run in the background in short steps, never while a visitor’s page is being built. On a visitor’s request ShieldWave only registers its hooks and, with login protection on, checks for the ?author= trick. While the site is connected to a ShieldWave account (plugin 1.1.0 and later), it also prints one invisible tag, <meta name="shieldwave-verify">, on the home page, which lets shieldwave.io confirm that the domain is yours.

To prove that a core, plugin or theme file is untouched, ShieldWave compares it with the official checksums WordPress.org publishes, the same service WordPress uses for its own updates. During a scan it also asks WordPress.org for theme packages, plugin information and the list of WordPress releases. Those requests to WordPress.org are the only outside requests a default install makes. Everything else that leaves your server is off until you turn it on, and is listed below.

What it never does on its own

It never changes your files, users or settings on its own.

Some actions do change files, and each one runs only when you press its button or turn on its switch. Quarantine moves a file into a protected folder, and Restore puts the same bytes back. Replace with the original downloads the WordPress.org copy of a changed core, plugin or theme file and keeps the changed file in quarantine. Cleanup of injected code, or of a reported rule in .htaccess or .user.ini, shows the exact change, makes a backup first and can be undone. The switch that blocks PHP in uploads writes a block into the uploads .htaccess file, the switch for PHP in wp-includes and wp-content writes its own block into the .htaccess file of the WordPress folder, and the request firewall and virtual patches write their own loader files. Security updates, for the plugins you chose or, since 1.1.29, for every plugin with a known vulnerability, let WordPress’s own automatic updates install a release that fixes it. Every other fix is explained in plain words for you, your developer or your host to apply.

Besides those, it stores only its own data: settings, scan results, history and a file baseline, plus, for accounts that turn on two-factor login, the authenticator secret, encrypted with a key derived from your site’s own salts when your server’s PHP has libsodium (without it the secret stays readable, and the plugin’s settings say so), the recovery codes, kept only as hashes, and the public keys of passkeys.

The options added in 1.1.29 act only after you turn them on.

Block critical virtual patches automatically, security updates for every vulnerable plugin and edge rules (Cloudflare) are off until you turn them on, and virtual patches work only with the threat feed on. With automatic blocking on, a patch for a critical flaw that we reviewed as safe to block starts blocking without your choice per patch. With edge rules and your Cloudflare API token, the plugin creates, changes and removes rules in your zone’s custom rules, only rules whose description starts with “ShieldWave:”. Your own rules are counted and never changed. Turning the feature off, removing the token or deleting the plugin removes the rules it placed.

While the threat feed is on, a feed for a plugin version with a known flaw can switch off named parts of this plugin until you update, for 30 days at most. It can only switch off, never turn anything on or change a setting. The firewall, virtual patches, login limits, two-factor login, hardening, scanning and the Settings form are never on that list. WordPress shows a notice that names the advisory, and the activity log records when a part goes off and comes back.

Full protection changes settings only after you confirm its review.

Full protection, the first panel of Settings, shows what it turns on, what leaves the site and what stays as it is before anything changes. It leaves the login address where it is. After you confirm, it sends out only what the options it turns on send: the vulnerability lookup and the threat feed to shieldwave.io and the breached password check to Have I Been Pwned, as the table below lists. The AI second opinion stays off unless you tick its own box. Save all changes sends each changed settings group to your own site, as that group’s Save button does, and sends nothing outside the site.

It adds no tracking to the pages your visitors see.

Visitors get no ShieldWave badges or tracking. Only a signed-in administrator sees its item in the WordPress toolbar. By default the one addition is the invisible verification tag on the home page while the site is connected to a ShieldWave account. Two opt-in features add to forms: the bot check puts a small browser puzzle, or Cloudflare Turnstile with your own keys, on the login, registration and password reset forms, and the spam traps add a hidden field and a signed time stamp to comment, registration and contact forms.

It makes no outside request when it is activated or when admin pages load.

Requests happen when a scan runs, when you use an account action, and on a schedule only for the optional services you turn on: the threat feed, the vulnerability lookup, the AI second opinion and the account check-in, each once an hour. With the threat feed on, the plugin also asks every 15 minutes whether an urgent feed update is out. Edge rules with a Cloudflare token sync twice a day and after the feed or your plugins change. The breached password check and Cloudflare Turnstile send requests only while someone sets a password or fills in a form. Slack and webhook alerts go out only with an alert, after you save an address.

The sign-in features change no content.

Login protection pauses logins after repeated failures, per address and per user name. While logins are paused, the activity log records the address, the time and the user name typed (the name only when that account exists), kept for the period set in the plugin, 90 days by default. After a successful login it sets one cookie on your site, named shieldwave_kd_ followed by a code. It holds only a random identifier and lets that browser keep signing in while someone else guesses the password for the same account. It expires after 90 days and stops working when the password changes. Two-factor login asks for a code from your authenticator app or a passkey, only for accounts that turned it on. Passkey sign-in without a password, the bot check, the breached password check, a hidden login address, a minimum password length, the idle sign-out for administrators and the email on a sign-in from a new browser are off until you turn them on.

What leaves your server

ServiceWhat is sentNever sent
WordPress.orgWhen a scan runsOn by default Your WordPress version and language, and the folder name and version of each plugin and theme, to fetch their official checksums, theme packages and plugin information. File contents. Like WordPress’s own update checks, these requests carry your site address in the user agent.
Vulnerability lookupWith each scan and once an hourOpt-in Your WordPress version, and the folder name and version of each installed plugin and theme, premium ones included. Your site address, an account or any personal data.
Threat feedOnce an hour, and a check for an urgent update every 15 minutesOpt-in Nothing about your site. The plugin downloads a signed file. The requests, the 15-minute check included, say only which plugin version is asking. Anything about your site.
AI second opinionOnly for a file the rules cannot judgeOpt-in A redacted excerpt of that file, its fingerprints, your admin language and a salted hash that stands in for your site. Your site address, email and IP addresses, server paths, passwords, keys or tokens, and configuration, backup, dump and log files such as wp-config.php, .env or .sql dumps.
ShieldWave accountOnly after you connect oneOpt-in This site’s id and address, scan results and the list of installed plugins and themes, so the dashboard can show them. Posts, pages, comments, user names, email addresses or passwords.
Have I Been Pwned, Pwned PasswordsWhen a password is set, and weekly at sign-inOpt-in The first 5 characters of the password’s SHA-1 hash. The service answers with every known hash that starts with them, and the plugin compares the rest on your server. The password, the rest of its hash, the user name or your site address.
Slack and webhook alertsWith each alert, only after you save an addressOpt-in Each alert also goes to hooks.slack.com or to your own https address: the site address, the time and the alert text, with account names, email addresses, visitor addresses and issue paths. A webhook can be signed with HMAC-SHA256 and a secret you choose. The fix text of the alert. The addresses and the secret are stored encrypted, never logged, never exported and never shown again.
Cloudflare TurnstileOn the login, registration and password reset forms, only with your own keysOpt-in The visitor’s browser loads Cloudflare’s script on those forms. Your server sends the answer token with your secret key to Cloudflare to check it, with WordPress’s default user agent, which carries your site address. The user name, the password or anything else typed into the form.
Cloudflare API, edge rulesTwice a day and after the feed or your plugins change, only with your own API tokenOpt-in Your token, the site’s host name to find the zone, and the edge rules that concern your PHP version and plugins, sent to api.cloudflare.com. The plugin reads your zone’s custom rules to count them and changes only rules whose description starts with “ShieldWave:”. Without a token nothing is sent, and the settings screen shows each rule to paste by hand. The token to anyone but api.cloudflare.com, shieldwave.io included. It is stored encrypted, never logged and never shown again.

Requests to ShieldWave identify themselves as ShieldWave-Security/1.1.30 (the number is the installed version). WordPress adds your site address to every outgoing request by default. ShieldWave replaces that with a neutral value, because a service that promises not to know your site should not receive its address in a header. Like any web request, each one still comes from your server’s IP address.

The threat feed is signed. Check it yourself.

Detection rules decide what the scanner flags, so a forged feed could hide real malware or raise false alarms. That is why the plugin accepts a feed only when all of these hold:

  1. The document is signed with Ed25519 over the bytes shieldwave-intel-v1\n followed by the payload, and the signature verifies against a public key built into the plugin.
  2. It has not expired. A feed is valid for seven days. After that its rules stop applying at once; its lists of known good and bad files are kept seven more days, then dropped.
  3. Its version is not older than the one the site already has, so an old feed cannot be replayed.
  4. Every rule and list stays within fixed size and pattern limits; anything outside them is dropped.

The key is published here and ships inside the plugin (SHIELDWAVE_SIGNING_KEYS in shieldwave-security.php), so you can compare the two. Since 1.1.30 the plugin also pins a second public key, kept offline for the day the first key is lost (SECOND_PUBLIC_KEY in includes/class-signature.php).

Algorithm
Ed25519
Public key (base64)
B2PRMUPcLPijkr6jqD/rGhoOqhPpqM1N4NGPto8rs+w=
SHA-256 of the key
8fd2b0e2 b65c1bf1 1ae0dfbf 3a0d977b b911f9be 17dddfb0 615c227f 0a6b4356
Feed address
https://shieldwave.io/api/plugin/intel

A short script does the same check as the plugin, with the key pinned inside it rather than fetched from us. It needs Node.js 18 or newer and has no dependencies.

# download the verifier, read it, then run it
curl -O https://shieldwave.io/verify/shieldwave-verify-feed.mjs
node shieldwave-verify-feed.mjs

It prints whether the signature is valid, the key fingerprint, when the feed was issued and expires, and exactly what it holds right now: rules, overrides and file fingerprints. Change a single byte of a saved copy and run it on the file to see the check fail.

The AI second opinion, precisely

It is off until you turn it on, and it is used only for a file the local rules cannot judge on their own. Before anything leaves your server, the excerpt is cut to the lines around the suspicious code, at most 6,000 characters, and cleaned:

  • your site’s host names become example.com;
  • email addresses become user@example.invalid;
  • IPv4 addresses become 0.0.0.0 and IPv6 addresses ::ip-redacted;
  • the path of your WordPress folder becomes /path/to/wordpress, and home folders become /home/user or /Users/user;
  • every DB_ constant, constants with key, salt, secret, pass or token in their name, the arguments of database connections, values of 6 characters or more assigned to names like key, token, secret or password, well-known token formats and long hexadecimal strings become [redacted];
  • very long strings are shortened so the structure survives but the content does not.

Other web addresses stay. If any step fails, nothing is sent. Files named wp-config or .env with any ending, .htpasswd, .user.ini, php.ini or auth.json, backup copies, database dumps (.sql), logs and .ini files are never read for an opinion. Plugin versions before 1.1.10 removed only host names, email addresses, passwords and keys.

Your site is identified only by a salted hash that cannot be turned back into its address. The excerpt is reviewed by a language model run by our AI provider, a US company, passed as material to analyse and guarded against instructions hidden in the code. The verdict is stored by the file’s fingerprint and reused when the same file shows up on another site.

What it is not

  • It is not a cloud web application firewall. Its optional request firewall, off until you turn it on, checks requests on your server with local rules that ship with plugin updates, and sends no request data anywhere. A blocked request has still reached your server. The optional edge rules use your own Cloudflare zone and plan, and cover only flaws for which the feed has a rule.
  • It cannot stop flaws in PHP itself, such as php2shell (CVE-2026-109618 and CVE-2026-109619), which run before any plugin loads, and the feed has no edge rule for php2shell. Updating PHP is the fix. When the site’s PHP is below the fixed release, the plugin warns administrators at once. The warning reads the version number only, so it asks you to check with your host. On PHP-FPM and LiteSpeed under Linux, a notice says when the PHP process serving the page still runs a file replaced on disk, which usually means PHP was updated without a restart. It checks only that one process and does not show whether the fix is installed.
  • It does not clean a hacked site for you. It finds malware, explains it and tells you what to do. Code injected into a theme, a custom plugin, uploads, posts or options it removes only after you approve each change.
  • It cannot protect a site from someone who already has an administrator account.
  • Login protection counts the address of the connection, never a header a request can fake. Behind a proxy or CDN that is the proxy’s address until you list the proxy’s addresses as trusted and pick the header that carries the visitor’s address. Without that, a lockout applies to everyone arriving through the proxy.
  • A check that could not run, for example because WordPress.org did not answer, is reported as not run. It is never counted as passed.

This page is about the plugin that runs inside your WordPress. The ShieldWave scanner that checks a site from the outside keeps to a set traffic budget and slows down or stops if a server is under strain. How that works is set out on How ShieldWave scans a live site.

Found a problem?

If something here is wrong, or you find a security issue in ShieldWave itself, please follow the vulnerability disclosure policy. The exact plugin package this page describes is at shieldwave.io/api/plugin/download; it is licensed under the GPL, so every claim here can be checked against its source.