WordPress Plugin Security Starts as a Visibility Problem

WordPress Security

WordPress plugin security is usually discussed as a code quality problem, but for most live sites it starts as a visibility problem. The information you would need to judge an estate exists in the database, in cron, and in public advisory feeds. It is just scattered across places no admin screen shows you.

The argument nobody wins

The criticism is familiar. WordPress is insecure because anyone can bolt forty plugins from forty strangers onto a site and never look at them again. Say it in any developer forum and you will get agreement within a minute.

The defense is equally familiar. That is not WordPress’s fault. It is the site owner’s fault for installing carelessly, or the host’s fault, or the plugin author’s fault. I am on the defending side more often than not, and I have made the case that WordPress still beats the AI site builders where it counts.

Here is my problem with that exchange, as someone who has run a WordPress development business for years: the defense is technically correct and practically useless. “Be more careful” is not a mechanism. It gives nobody a way to act differently on Monday morning.

Both sides are arguing about blame. Almost nobody is arguing about what a site owner can actually see.

Your plugins screen shows three fields

Open any WordPress admin. The plugins screen gives you a name, a version number, and a description the author wrote about themselves.

That is the entire interface most people have for reasoning about risk. It does not tell you which of those plugins has a published vulnerability at the version you actually have installed, as opposed to merely appearing somewhere in an advisory database. It does not tell you which one loads 19 KB of autoloaded options into every single page request. It does not tell you that the plugin you deleted in 2019 left a scheduled job still firing every hour.

None of that is hidden. It sits in wp_options, in the cron array, in SHOW TABLE STATUS, and in public feeds like the WPVulnerability database. Getting to it means being a developer with a database client and a free afternoon.

So we have an ecosystem whose central criticism is a security one, and the people responsible for those sites cannot answer basic questions about them without writing SQL. That gap is where I think the useful work is. It is the same shape as the technical debt that accumulates quietly in WordPress: not dramatic, not visible, and expensive later.

What a ten-year-old site leaves behind

We pointed a read-only audit at one of our own sites. It has been alive since 2015 and it is not unusual in any way.

The orphaned tables told a story. A contact form plugin, long since removed, had left three tables holding 71 form submissions and 642 field-value rows. Names, email addresses, and messages from people who contacted the business years ago, sitting in tables that no privacy tool on that site can see, because no installed plugin claims them.

An invoicing plugin had left eight tables, all empty. Installed, never really used, deleted, and never cleaned up. A background job queue had 35 queued actions and 93 log rows belonging to a plugin nobody could name.

Nothing there is a vulnerability in the CVE sense. No scanner would flag it. But if you had asked me before that audit whether we held a decade of stranded contact form submissions on that site, I would have said no, confidently, and I would have been wrong.

You cannot make a judgment about an estate you cannot see. Most WordPress security advice assumes visibility that nobody actually has.

So I built something that can only look

The result is Auditra, a free plugin that turns the site it runs on into a read-only MCP server. You enable an endpoint, generate a token, paste the connection URL into an AI client, and then ask questions in plain language. Which plugins are vulnerable at the versions installed. What is bloating the options table. What did deleted plugins leave behind.

The interesting part is not the tool list. It is the three things it refuses to do, each of which cost me something.

It cannot change anything. No activating, no deactivating, no updating, no writing to the database at all. That is structural rather than a promise: there is no write call anywhere in the codebase, and the build fails if one is ever added. A tool that can only look has nothing to sell you afterward.

It does not score anything. No grades, no risk numbers, no “this plugin is dangerous.” Scores sell, which is precisely why so much security tooling has them and precisely why I do not trust them. The plugin returns facts with documented thresholds and leaves the judgment to the model reading them, which also means the analysis improves as models improve without me shipping anything. That is the same principle behind keeping AI on a short leash while coding: give it accurate context, not conclusions.

Saying “I don’t know” is the whole design

The decision I spent longest on sounds trivial. If the plugin could not check anything at all, what should it return?

The obvious answer is an empty list of findings. That is what most tools do, and it is wrong, because an empty list reads as clean. A security tool that implies “clean” when it checked nothing is worse than no tool, because it manufactures confidence that was never earned.

So it returns no findings list at all in that case. Not an empty one. A response saying what could not be checked, why, when the data was last fetched, and when it will retry. When only some plugins could be checked, the ones that were skipped are named individually. Every data source reports its own coverage.

That is a small technical decision, but it is the entire argument in miniature. The reason WordPress security discourse is so poor is that too much of the tooling is confidently wrong. Scanners emit scores. Plugins claim protection. Almost nothing ever says “I could not check that.” I would rather ship something that admits ignorance loudly than something that looks authoritative and is occasionally lying to you.

What this does not fix

Plenty. Seeing that a plugin has been unmaintained for three years does not patch it. Knowing an orphaned table holds old contact submissions does not delete it, and deliberately so, because a read-only tool cannot make that mistake on your behalf.

It also needs an AI client on the other end, which today means a narrower audience than the WordPress user base. I would rather say that plainly than pretend otherwise.

And there is a fair objection I should answer rather than dodge: this adds an HTTP endpoint that returns information about your site, which is a new surface. True. It ships disabled and answers 404 until an administrator turns it on, it requires a token compared in constant time, it is rate-limited, it is revocable in one click, and it exposes no post content, no user accounts, no credentials, and no option values. Only names and sizes. That is a considered trade, not an accident, and the readme spells out exactly what an enabled endpoint exposes so nobody has to take my word for it.

The plugin ecosystem is the best thing about WordPress. It is also the thing that makes a ten-year-old site an archaeological dig. I do not think that tension is going away, and I do not think another scanner with a letter grade helps. Better visibility might, a little. That is the whole intention, and it is a small one. The rest of the argument belongs to the ecosystem, which has been having it for fifteen years and will probably still be having it in another fifteen.

Not sure what your plugin estate is actually doing?

We maintain WordPress sites that have been running for a decade or more, and we start by finding out what is really on them.

See our WordPress maintenance service

Visited 1 times, 1 visit(s) today

Related Posts

Search

 

Popular Posts

@macronimous Copyright © 2026.
Visit Main Site