Most WordPress Plugins on GitHub Never Reach the Official Directory. Here’s Why That’s a Security Problem.
What we saw
We monitor traffic across the sites we watch, and we track IP addresses with a history of malicious behavior. A pattern kept surfacing in the logs.
One flagged address would visit a site briefly, touching the kind of paths that reveal which plugins are installed. Reconnaissance, essentially, building an inventory of what a site runs. Then, hours later, a different flagged address would return and go straight at a single plugin. Not a spray of generic exploit attempts across everything, but a focused probe at one specific target. And that target was consistently a plugin that was not listed in the official WordPress.org directory.
We see access logs, not payloads, so to be precise about the evidence: we are describing the request pattern and its timing, not the contents of the attack. But the two-phase shape was consistent and it repeated. Enumerate from one address. Return later, from another, and attack a specific non-directory plugin.
That raised a question we could not answer from the logs alone. To attack a plugin’s code, you generally have to study it first. And a WordPress plugin’s logic runs server-side, in PHP. Unlike a client-side JavaScript application, you cannot read a plugin’s vulnerable code just by loading the site. The server executes the code and sends you only the result. So an attacker who wants to find a flaw in a specific plugin has to get the source from somewhere.
For the roughly 60,000 plugins in the WordPress.org directory, that somewhere is the directory itself. The full source ships in every download, and known vulnerabilities usually carry public CVEs. There is little to research.
But for a plugin that exists only outside the directory, where does the source come from? The obvious candidate is GitHub. So we went looking to measure something concrete: how much WordPress plugin source, specifically the kind that is not in the official directory, is sitting publicly on GitHub, available to anyone who wants to read it.
This post is what we found. To be clear up front, the link between the attacks we observed and GitHub specifically is still a hypothesis we are actively testing. What follows establishes that the source exposure the theory requires is real, and large.
Why source on GitHub changes the attacker’s math
A plugin published only as a GitHub repository is fully readable by anyone. They can clone it, read every line, and study it for weaknesses at their leisure, without ever touching the target site during the research phase. The obscurity that is often assumed to protect a niche plugin is not protection at all. The code is completely public. It is simply published somewhere other than the official channel.
That is the crux of it. A directory plugin and a GitHub-only plugin can be equally exposed at the source level. The difference is that the GitHub-only plugin sits outside the systems built around the directory: the update mechanism, the security team, the coordinated disclosure process. The exposure is the same. The safety net is not.
Finding one: currency
We swept GitHub for repositories tagged as WordPress plugins, extracted each plugin’s slug from its header, and checked that slug against the WordPress.org plugin API.
Among 3,137 plugin repositories that were actively pushed to in 2026, 63.3 percent (1,987) do not exist on WordPress.org.
These are not abandoned experiments. They are plugins people are actively working on this year, distributed as source on GitHub and nowhere else in the official ecosystem. And many of them have real reach: 450 have five or more stars, 540 have been forked at least once, and the most-starred carries more than 3,300 stars. Forks matter especially, because once code is forked it is copied and scattered, and deleting or archiving the original no longer recalls it.
Roughly a third carry no clear open-source license, and more than a third are owned by individual accounts rather than organizations. Informal, single-maintainer projects are precisely the population least likely to receive a coordinated security response when something goes wrong.
The headline here is simple: even among plugins that are actively maintained today, nearly two-thirds live outside the directory. This is not a story about old, forgotten code. Which brings us to the code that is old and forgotten.
Finding two: abandonment
In an earlier sweep covering repositories pushed between 2015 and 2019, we found 1,642 GitHub-only plugins. In that population, 86.9 percent of all the plugin repositories we examined were not in the directory, and the GitHub-only set averages 8.5 years since its last change.
197 of them (12 percent) are explicitly archived by their own authors. Archiving is a deliberate signal. It is a maintainer saying “this is finished, I am not working on it anymore.” What it does not do is remove anything. The source stays public. The plugin stays installable. The code an attacker would study is exactly where it was.
And this is not a hobbyist-only phenomenon. Of the archived, GitHub-only plugins that still carry five or more stars, 40 percent are owned by organizations rather than individuals. Companies and established development shops do this too. WP Engine, one of the largest WordPress hosts in the world, has an archived plugin repository whose name literally ends in “DEPRECATED,” still public and cloneable. Mozilla’s MDN team archived a WordPress plugin and left the source up. So did Liquid Web, and a number of well-regarded agencies.
We want to be clear that none of this is negligence. Archiving deprecated code is normal, correct behavior. The point is structural, not a criticism of any author: the source persists regardless of whether anyone is maintaining it, and that persistence is the exposure.
Here is a sample of archived, GitHub-only plugins that still have meaningful reach:
| Stars | Plugin | Last push | Owner |
|---|---|---|---|
| 66 | genesis-header-nav | 2018-01-13 | Individual |
| 60 | gravityforms-repeater | 2018-01-12 | Individual |
| 57 | patterns | 2017-03-26 | Individual |
| 54 | user-feedback | 2017-12-04 | Organization |
| 51 | acf-gutenberg | 2018-10-30 | Individual |
| 37 | promote-mdn (Mozilla MDN) | 2019-03-30 | Organization |
| 31 | wpe-search-DEPRECATED (WP Engine) | 2015-08-20 | Organization |
| 23 | bundle | 2018-08-21 | Organization |
| 17 | wp404 | 2016-03-17 | Individual |
| 15 | find-shortcodes | 2016-11-03 | Organization |
| 11 | flynt-core | 2019-03-15 | Organization |
47 archived, GitHub-only plugins in this sample carry five or more stars. 19 of them (40 percent) are organization-owned.
What we are doing to confirm it
The attack pattern we observed and the source exposure we measured point at each other. But pointing at each other is not proof. We have not yet demonstrated that attackers use GitHub as the intermediate source between the recon visit and the attack.
So we built something to test it directly. We deployed instrumented canary plugins, published only to GitHub and never to the directory, engineered so that the only way to learn how to interact with certain endpoints is to read the source. There is no other discovery path. A probe against one of those endpoints is unambiguous proof that someone obtained the code from GitHub. We will report those results in a follow-up.
What to do about it
If you publish a plugin only on GitHub, treat its source as fully public and studyable, and build that into your threat model rather than assuming that being unlisted keeps you safe. It does not.
If you run a plugin sourced from GitHub rather than from the directory, understand that it very likely sits outside the update and vulnerability-disclosure paths that directory plugins benefit from. Tracking its security is on you.
If you host or manage WordPress at scale, plugins installed from outside the directory are a specific blind spot. They are worth inventorying on their own terms, because the usual directory-based tooling will not see them coming.
Method: We swept GitHub for repositories tagged wordpress-plugin, extracted each plugin’s slug from its header, and checked that slug against the WordPress.org plugin API. Two populations are reported separately: repositories pushed in 2026 (n=3,137) and an earlier 2015 to 2019 window (n=1,642 GitHub-only). We spot-checked the GitHub-only classification against a random 50-row sample and found 0 false “not in directory” results. One known limitation: our slug check keys on a plugin’s Text Domain, which can differ from its actual directory slug, a small source of overcounting that we controlled for in the verification sample. All figures are reproducible from the same queries.
