About WP Beacon

An open-data explorer watching wordpress.org for plugin supply-chain risk.

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 SVN svn log reconstructs the committer list per plugin, which is not exposed on the public API but is the strongest ownership-transfer signal.

Signals we watch

RuleFires whenSeverity
new_committer_young_accountAn SVN committer's account was less than 90 days old when they got their first commit on the pluginCritical
author_changedThe plugin's primary author profile URL changed between crawlsHigh
version_compare_trapA release version is structured to beat a future patch via PHP's version_compare() (e.g. 6.02 beats 6.0.9)High
plugin_closedwordpress.org closes the pluginMedium
release_after_dormancyA plugin with 10k+ installs releases again after more than a year of silenceMedium
contributor_addedA 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.

EndpointReturns
GET /statusGlobal counts, last crawl + last detect timestamps
GET /events?severity=critical&rule=XPaginated event feed with details
GET /audits?verdict=malicious&since=2026-01-01Published 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=100Install-ranked leaderboard
GET /top-committers?limit=100SVN-access-ranked leaderboard
GET /check?slugs=a,b,cBulk 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.