When A WordPress Plugin Is Removed From The Repository, Nobody Tells The Site.
A plugin pulled from WordPress.org stays installed, stays active, and stops getting updates. We probed the API to see what a site can actually detect.
Short answer: when a wordpress plugin removed from repository is sitting on a site, nothing happens. It stays installed, stays active, and stops receiving updates. WordPress shows no badge, sends no email, and the plugins screen looks completely normal. The only outward signal is an absence, and an absence is not something anyone notices.
Patchstack counted 1,614 plugins and themes removed from the WordPress.org repository during 2024 over security issues the developers never fixed.
Every one of those is still running somewhere.
Why does a removed plugin keep working?
Because removal is a change to the directory, not to the site.
WordPress asks wordpress.org “is there a newer version of this plugin”. A delisted plugin returns no newer version, which is byte for byte the same answer as a plugin that is perfectly up to date. The site cannot tell those apart, so it does the sensible thing and shows you nothing.

visible signal somewhere. The fourth, the one that means an unfixed vulnerability was serious enough for the directory to pull the plugin, produces nothing.*
Can you tell if a WordPress plugin was removed from the repository by asking the directory?
This is where it gets worse, and I tested it rather than assuming.
I queried the WordPress.org plugin information API for four slugs: two plugins I know are listed, one that has been delisted, and one slug I invented purely as a control.

directory page. The delisted slug and the slug I made up for this test return exactly the same thing: 404 from the API, 301 from the directory page. The control row is there on purpose, because without it you would read the 404 as proof of removal.*
So the directory will not tell you why a plugin is absent. It will not tell you when it went, or what it went for. “Pulled over an unpatched vulnerability” and “never existed” are the same response.
Inside wp-admin the effect is quieter still. Search the installer for a delisted plugin that is running on the site right now:

that code may be installed and active. WordPress does not connect those two facts, because nothing in the software is looking for the contradiction.*
What actually detects it
Three signals, and only the third is reliable.
The plugin’s readme, as shipped. Compare the version installed on disk against the last version the directory ever published. Useful, but it only works while the directory still remembers, and it tells you nothing about severity.
A long-quiet plugin. Anything with no release in eighteen months deserves a look. This catches genuinely abandoned code as well, which is a feature. It also produces false positives on small, finished plugins that simply do not need changes.
An advisory feed matched against the installed inventory. This is the one that works. Not “what is in the directory”, but “what is actually installed here, at what version, and does anything in the advisory record say that version is a problem”.
Note the direction of the question. Every unreliable version of this check starts from a name and asks the directory about it. The reliable version starts from the site and asks an advisory source about what it found.
That is also why this particular check cannot run from the outside. A scan of a domain can see plenty, but the list of what is installed and at which version is only readable from inside the install.
Running the check across a whole portfolio
The check is one API call per plugin, so it scales to a portfolio easily. Here it is against every plugin on one install:

REVIEW line is a false positive and it isthe most instructive line on the screen. Hello Dolly ships with WordPress. Its folder is hello, its directory slug is hello-dolly, and both are on version 1.7.2. A check that reads folder names and trusts the 404 sends you investigating a plugin that prints song lyrics in the admin.*
Two rules fall out of that, and they are the difference between a check you can run unattended and one that cries wolf:
- Resolve the real slug before trusting a 404. The folder name on disk is not
authoritative. Read the slug the plugin’s own update data reports.
- Treat a 404 as “review”, never as “removed”. As the earlier probe showed, the API
cannot distinguish removal from a name that never existed. A check that reports removal from a 404 alone is stating something it does not know.
If your monitoring tells an agency a plugin was pulled and it turns out to be Hello Dolly, you have not built a security check. You have built something people switch off.
What to do on Monday
Pick the client site you have not opened in a fortnight and do three things.
Sort the plugins list by whatever your install shows for last update, and look at the bottom of that list. Take the five oldest and search each slug in the installer. Anything that returns “No plugins found” while sitting active on the site is your answer, and it wants a decision today rather than at the next review.
Then check whether that plugin has a maintained fork or a documented replacement, because “remove it” is rarely available when the thing renders half the client’s pages.
While you are in there, the same site is worth checking for the PHP version it runs on, since an abandoned plugin and an unsupported PHP branch tend to be found on the same install.
Where Protuno fits, and where it does not
We are building this check into Rook, the Security agent, as Vulnerability Watch: it reads what is actually installed on a connected site and matches it against advisory feeds every morning, so you hear the day something you run becomes a problem rather than at the next audit.
Straight about status, because that is the whole argument of this blog: the Super Agents are built and named but not live yet. Not on your sites, not on ours. The free audit is live and runs 54 read-only checks from a domain alone, and this is deliberately not one of them, for the reason above: it needs to read inside the install.
Until it ships, the manual version is the plugins list and the installer search box. It takes about four minutes per site, which is fine for one site and is exactly the arithmetic that breaks down across a portfolio.
And if the scheduler on that site has stopped, its auto-updates have not been running either, which is worth ruling out first.
Comments