---
title: "WordPress Security Without A Security Plugin That Fights Your Host"
url: https://hostmy.blog/wordpress-security/
date: 2026-09-11
modified: 2026-09-03
lang: en
author: "Aditya Sharma"
description: "Most WordPress compromises trace back to old code or stolen credentials. Here is what to fix, layer by layer, and what your plugin duplicates."
categories:
  - "WordPress"
image: https://hostmy.blog/wp-content/uploads/2026/09/hmb-card-1855-1024x538.jpg
word_count: 1758
---

# WordPress Security Without A Security Plugin That Fights Your Host

Two things get WordPress sites compromised at scale: code with a known published vulnerability that nobody updated, and credentials that somebody else has.

Almost everything sold as WordPress security addresses a third category, the live attack, which is real but is the layer your host and your CDN are already sitting in front of. That mismatch is why a site can run a heavy security plugin, show a satisfying count of blocked attacks, and still get taken over through an outdated slider plugin.

Here is the layer model, what belongs at each layer, and where a plugin ends up fighting the infrastructure it sits on.

Five layers, each able to fail on its own

Five layers, each able to fail on its own

Edge
rate limits, bot rules, WAF

Server
file permissions, PHP version, user isolation

WordPress core
minor releases applied automatically

Application accounts
roles, two factor, no shared admin login

Recovery
an offsite copy you have restored at least once

A security plugin operates at layer three. The layers above and below it are the ones a host controls, which is where plugin and host most often fight.

## Security is five layers, and a plugin can only reach two of them

| Layer | Who owns it | What belongs here |
| ----- | ----------- | ----------------- |
| Edge | CDN or host WAF | Rate limiting, bot filtering, DDoS absorption |
| Server | Host or your sysadmin | PHP version, file permissions, fail2ban, isolation between sites |
| WordPress core and code | You | Updates, removing unused code, checksums |
| Accounts and access | You | Least privilege, 2FA, unique credentials |
| Recovery | You | Offsite backups you have actually restored |

A plugin operates at layers three and four, and it does that well. When it tries to operate at layers one and two, it is doing the work inside PHP, after WordPress has already booted, which is both slower and later than the same work done at the edge.

That is the practical definition of a plugin fighting the host: two systems doing the same job, one of them in the wrong place, and neither aware of the other. Which of the top two layers somebody else already owns is worth settling first, and it is a large part of [what a managed platform covers at the edge](/managed-wordpress-hosting/).

## The four duplications that cause real problems

**A PHP-level firewall behind an edge WAF.** The edge already dropped the obvious traffic. What reaches PHP now gets inspected again, using your CPU, on every request including cached ones in some configurations. You pay response time for a second opinion on traffic that was already filtered.

**A malware scanner that walks the filesystem on a schedule.** Scanning every file under `wp-content` is genuinely expensive on shared hosting, and it is the single most common reason a site trips a hosting resource limit and slows down for reasons nobody can explain. If your host runs server-side scanning already, running a second scanner in PHP buys you very little.

**Login rate limiting in PHP when the server has fail2ban.** Every blocked attempt in the PHP version still boots WordPress, still connects to the database, and still writes a row to a log table. The server-level version drops the connection before any of that.

**IP blocklists stored in the database.** These grow without limit, get autoloaded in some implementations, and are consulted on every request. The edge does this in memory, for free, at a scale no plugin can match.

## What actually protects a WordPress site, in priority order

### 1. Update the code, especially plugins with published advisories

This is the boring one that prevents most incidents. Vulnerability disclosure is public, exploitation follows disclosure within days, and the window between the two is where sites are lost. An unpatched plugin sitting through that window belongs with [the quiet failures that never announce themselves](/what-breaks-when-nobody-is-watching/), because nothing on the site looks wrong while it is open.

Verify that what is on disk is what should be on disk:

`wp core verify-checksums
wp plugin verify-checksums --all`

Both compare files against the official WordPress.org hashes. Unexpected output means either a modified file or a plugin not distributed through WordPress.org, and you need to know which. The same argument covers the interpreter underneath, so [running a PHP release that still receives security patches](/wordpress-php-version/) is part of this layer rather than a separate project. This is also the fastest first look when you suspect a compromise.

### 2. Remove code you are not running

An inactive plugin is still a file on the disk. Unused themes are the same. Reducing the number of files that exist is the only security control with a negative maintenance cost, which is why it belongs in the same review as the one in [plugin bloat](/wordpress-plugin-bloat/).

Nulled or pirated premium plugins deserve naming directly. The business model of a nulled plugin is usually the backdoor inside it. There is no safe way to run one.

### 3. Fix the account layer, which is where credential theft lands

`wp user list --role=administrator --fields=ID,user_login,user_email,user_registered`

Read that list carefully. Administrator accounts belonging to a developer who finished the project in 2022, a former employee, or an agency you no longer work with are the usual finding. Every one of those is a live key.

Then the rules that follow: unique passwords, a manager to hold them, two factor on every administrator, and editors given the editor role rather than administrator because it was easier. Least privilege is unglamorous and it limits the blast radius of exactly the credential theft that a firewall cannot see.

Rotate the salts when in doubt, which invalidates every existing session:

`wp config shuffle-salts`

### 4. Close the two file-level holes that matter

Stop PHP from executing inside the uploads directory. An upload vulnerability becomes a full compromise only if the uploaded file can be run.

Apache, in `wp-content/uploads/.htaccess`:

`<FilesMatch "\.php$">
Require all denied
</FilesMatch>`

nginx, in the server block:

`location ~* /wp-content/uploads/.*\.php$ {
deny all;
}`

And turn off the built-in file editors, so an account compromise does not immediately become arbitrary code execution through the admin:

`wp config set DISALLOW_FILE_EDIT true --raw`

Check permissions while you are there. Files at 644, directories at 755, `wp-config.php` tighter at 640 or 600 where the setup allows. Nothing on the site should be world-writable:

`find . -type f -perm -o+w -not -path "./wp-content/cache/*" | head -20`

### 5. Keep a recovery path you have tested

Every layer above can fail. The recovery layer is what turns a compromise from a disaster into a bad afternoon: offsite backups, retained long enough that you can go back past the date of infection, and restored at least once so you know the archive works. That last part is the whole argument in [the restore that failed when it was needed](/wordpress-backup/).

## The hardening that is mostly theatre

**Renaming or hiding `wp-login.php`.** It stops the crudest bots and nothing else. Author enumeration through the REST API or author archives still reveals usernames, and any serious scan finds the new login path quickly. Meanwhile it breaks integrations, password managers and occasionally your own recovery flow at the worst moment.

**Blanket-disabling the REST API.** The block editor uses it. So do most modern integrations, and increasingly the mobile app and headless tooling. Disabling it site-wide breaks real functionality to close a surface that is authenticated for anything sensitive.

**Disabling XML-RPC without checking.** Reasonable on many sites, and it does remove a brute force vector. It also breaks Jetpack, the mobile app, and some publishing tools. Check what uses it before you switch it off, rather than after.

**Counting blocked attacks.** Background scanning traffic hits every public site continuously. A large number in that counter measures the internet, not your defences. Treat it as weather.

## What a security plugin is genuinely good for

Not an argument against plugins, an argument for using the parts that are not duplicated.

Two factor authentication, if your host does not provide it. An activity log, which is the single most useful artifact when something goes wrong, because it tells you which account changed what and when. Vulnerability notifications tied to your installed plugin list. File integrity alerting, if it is not already running at server level.

Those four are worth their weight. The edge firewall, the deep scanner and the IP blocklist usually are not, when the host already provides them. Ask your host what they run before you turn anything on, and turn off the layer that is duplicated rather than the one that is faster.

One adjacent job keeps getting pushed into security plugins where it does not belong: deciding which AI crawlers may read the site. That is a policy question answered in robots.txt and at the edge, not a threat to inspect in PHP. [RankReady](https://wordpress.org/plugins/rankready-ai-llm-seo/) is the WordPress AI SEO plugin we use for it, version 1.3.1, tested to WordPress 7.1, with about 300 active installs on WordPress.org. It runs alongside Rank Math, Yoast, AIOSEO or SEOPress without conflicting with them, takes about five minutes to configure, and what it changes is crawlability rather than your defences.

## If you think you are compromised, the order matters

Do not start by cleaning files. Cleaning in place, with the entry point still open, gets you reinfected and destroys the evidence you needed.

Take the site offline or behind maintenance mode. Take a forensic copy of files and database before changing anything, even a compromised one, because you will want it. Rotate all credentials, including hosting, database, FTP and every administrator account, then rotate the salts to kill live sessions. Restore from a backup dated before the first sign of the problem. Patch the entry point, which is usually an outdated plugin you can find by comparing checksums and update dates. Only then bring it back, and watch it closely for a week, using the kind of checks in [separating alerts worth waking for from noise](/wordpress-monitoring/).

## Where Host My Blog fits

Everything here is doable by hand, and the commands above are all of it. A capable owner with an afternoon can close the real holes on most sites.

The part that is hard to keep doing is the ongoing part: patching within days of an advisory rather than months, auditing the administrator list when people leave, and holding a backup you have actually restored. Host My Blog runs that cycle on the blogs we manage, as part of [the recurring patch and audit work billed monthly](/wordpress-maintenance-service/). If you patch promptly already, the plugin you are paying for is probably doing less than you think, and you can cancel it rather than hire us.

So, a question worth answering today: how many administrator accounts does your site have right now, and can you name every person behind them?