About WP Beacon
Why
Two recent WordPress.org incidents — Essential Plugin (31 plugins backdoored after a Flippa purchase) and Widget Logic (malicious 6.0.0 after a quiet ownership change) — were only caught after the fact, site by site. Both followed the same pattern: an attacker buys or is granted commit access to an established plugin with a large install base, waits months, then ships a dormant backdoor in a routine-looking release.
Detection today is reactive. WP Beacon flips that: continuously crawl wordpress.org's public surface, snapshot author and committer state per plugin, and flag the upstream signals before the payload activates.
Data sources
api.wordpress.org/plugins/info/1.2/?action=query_plugins— all ~58k plugins with author, contributors, active_installs, versions.profiles.wordpress.org/<slug>/— public profile pages for member-since, location, employer.plugins.svn.wordpress.org/<slug>/— anonymous SVNsvn logreconstructs the committer list per plugin, which is not exposed on the public API but is the strongest ownership-transfer signal.
Signals we watch
| Rule | Fires when | Severity |
|---|---|---|
| new_committer_young_account | An SVN committer's account was less than 90 days old when they got their first commit on the plugin | Critical |
| author_changed | The plugin's primary author profile URL changed between crawls | High |
| version_compare_trap | A release version is structured to beat a future patch via PHP's version_compare() (e.g. 6.02 beats 6.0.9) | High |
| plugin_closed | wordpress.org closes the plugin | Medium |
| release_after_dormancy | A plugin with 10k+ installs releases again after more than a year of silence | Medium |
| contributor_added | A new readme contributor appears (softer signal) | Low |
What this is not
WP Beacon is a signal layer, not a verdict. An alert means "look at this" — the actual malicious payload still has to be confirmed by reading the code. Legitimate ownership transfers and new committers happen all the time. The critical-severity combinations are designed to match the pattern of known attacks, not to replace judgment.
Public API
Every page on this site is also available as JSON under /wp-json/wpbeacon/v1/. Designed for automated consumers — host fleet dashboards, IDE integrations, security tooling.
| Endpoint | Returns |
|---|---|
| GET /status | Global counts, last crawl + last detect timestamps |
| GET /events?severity=critical&rule=X | Paginated event feed with details |
| GET /audits?verdict=malicious&since=2026-01-01 | Published audits. Defaults to active malicious findings (excludes cleaned, benign, and in-progress drafts). Each item includes verdict, cleanup status, suite size, IOC count, links, and an affected_slugs[] array — the full slug list a fleet operator can match installed plugins against (every slug for suite-level audits, headline slug for singles). |
| GET /audits/{id} | Full audit record: summary, evidence markdown, IOCs, affected plugins (suite-level), originating event, cleanup instructions, patched-zip URL. |
| GET /plugins/{slug} | Full plugin record: committers, contributors, versions, events |
| GET /authors/{slug} | Author profile + all plugins they touch + events |
| GET /top-authors?limit=100 | Install-ranked leaderboard |
| GET /top-committers?limit=100 | SVN-access-ranked leaderboard |
| GET /check?slugs=a,b,c | Bulk flag-status lookup (up to 200 slugs). Useful for host dashboards showing "is anything installed on this site flagged?" |
No authentication required — every data point served comes from public wp.org sources already.
RSS feed
Subscribe to /feed/audits.xml to get new published audits in your feed reader, Slack, or email gateway. Same publishability filter as the audit list — defaults to active malicious findings; pass ?verdict=cleaned, ?verdict=benign, or ?verdict=all to override.
RSS 2.0 with stable urn:wpbeacon:audit:{id} GUIDs so re-publishing an audit (e.g. after a cleanup-status change) doesn't duplicate entries in your reader.