If the homepage made a claim, this page is the receipts. Each finding below is either anonymized from a specific customer site or a pattern observed across many. Site names and identifying details are redacted; the operational shape is exactly what was seen.

What an alert actually looks like

Four real alerts pulled directly from a customer Slack channel. Customer name is redacted in-image. Phone status bars, timestamps, severity colors, rule names, snooze controls — exactly what arrives.

Tap any alert to view full size.

Anonymized from a real site A nonprofit running a multi-language WordPress

Cron had been off, and the site had stopped noticing

The site was responding normally. Pages rendered, the admin loaded, content updated. The internal scheduler, however, had drifted: 68 of 69 scheduled hooks were overdue, and the most-overdue hook had been delayed by 1,825 days.

The downstream debris was the giveaway. A helper plugin whose entire purpose is to catch "missed scheduled posts" was running 100–200 times per day, 500–700 ms each — roughly two minutes of PHP CPU spent every day papering over a scheduler that no longer ran on time. To anyone reading the homepage, the site was fine. To anyone reading the activity, it had been broken for years.

The operator switched off the internal scheduler in wp-config.php and routed scheduled work through the host's OS-level cron. Cleanup of the orphaned drafts, stale transients, and unprocessed action-queue rows took the next two weeks.

Anonymized from a real site A small-business WordPress, first hours of monitoring

The site was publishing its user directory by default

At 15:01 UTC, three minutes after the integration started shipping signals, an unfamiliar IP made an unauthenticated request to /wp-json/wp/v2/users/. The endpoint returned an HTTP 200 with the full author list — usernames, slugs, Gravatar hashes — to a caller that had never logged in.

Three minutes after that, the same IP started a 60-request burst against //xmlrpc.php (the leading double slash is a routine bypass for naive .htaccess rules), targeting one of the accounts it had just learned existed. Ten other IPs joined within fourteen minutes. They all converged on the same target account.

The site's security plugin was installed and active. Neither of the two recon endpoints had been disabled by default.

The operator unregistered the REST users endpoint in a small mu-plugin and returned 404 on ?author=N author scans. The harvested usernames remained valid, but a hidden-login plugin made them useless without the login URL.

Recurring pattern Observed repeatedly across WordPress customer fleet

The attacker doesn't live on one IP

In a 2 hour 45 minute window, one site recorded 77 failed login attempts from 11 distinct IPs. Per-IP rate limiting did nothing — no individual address attempted enough to trip the limiter. The signal was elsewhere: 10 of the 11 IPs all produced the same hashed username.

The integration hashes usernames before shipping, with a per-tenant HMAC key. That means the same target account viewed from multiple sources is recognizable as the same target, while the username itself never leaves the site in cleartext. Identical hashes across distributed IPs is the diagnostic. The attacker did not live anywhere in particular — they were renting addresses by the hour and pointing all of them at the same account.

The operator locked the active IPs at the CDN, added a per-account lockout policy (so a brute force against one account hits a wall even when the source addresses keep rotating), and assumed the target username was now publicly known — rotated the password and enabled 2FA.

Anonymized from a real site A contracting business's WordPress

The site was sending email it never authorized

Seven outbound emails fired from the site within a six-minute window, all originating from the same external IP that posted to /xmlrpc.php without authenticating. The xmlrpc endpoint exposes methods that can cause WordPress to send mail — new user notification, comment notification, password reset — without a logged-in session. The site was being used as a relay.

The owner discovered it 35 minutes after the last outbound message, by which time the mail was already out the door. The abuse window was six minutes wide. The detection-to-action gap was 35 minutes. Domains in this position typically end up on a blocklist if the volume crosses a threshold, which complicates legitimate email for weeks.

The operator blocked xmlrpc.php at the web server (returning 403 before PHP runs at all) and ran the domain against the major blocklists. It hadn't landed on any of them; the response was fast enough.

Recurring pattern Observed across multiple WordPress sites with vendored plugins

The plugin folder name was the supply-chain tell

Properly-installed WordPress plugins live in folders named like plugin-slug/. Folders with literal spaces, trailing -latest-N, or version-with-build suffixes like plugin_name 4.0-123/ are almost always re-uploaded ZIPs from a mirror or a nulled-plugin site. They ship with stale bundled libraries — updater shims, helpers, vendor code — that produce loud deprecation noise on modern PHP.

On one nonprofit's site, a plugin folder named literally divi_module_acf 4.0-123 — space and version-build suffix included — accounted for 11,038 PHP deprecation warnings in seven days. That was roughly 86% of the site's entire deprecation-warning volume. The repeating warning was from a years-old bundled updater shim inside the plugin. The site owner could not confidently say where the plugin had come from.

The operator removed the plugin, redownloaded it from the canonical vendor channel, and reinstalled under a clean folder name. The deprecation volume dropped by the expected proportion within a day.

Anonymized from a real site A nonprofit's multi-language WordPress

A dormant admin account was doing more work than any human

One of the site's WordPress user accounts had not logged in for months. The person it belonged to had moved on. The account was, however, still attached to authored content and to assets managed by a downloadable-content plugin — and that plugin was running 22+ capability checks per minute against the user, asking whether the dormant account could still access its own files. The check rate looked like a humanly-active user. The user was not active.

The compounding problem is that dormant accounts with elevated roles are a standard initial-access vector. The site owner's first instinct, when asked about the account, was to defend the importance of the user's historical articles — the connection between "still has a role" and "still being asked permission questions about every minute" was not visible without the activity record.

The operator reassigned the historical content to a currently-active editor, demoted the dormant account to no-role, and rotated the password. The capability-check rate against that user dropped to zero.

Anonymized from a real site A one-person agency's WordPress, fronted by a WAF

The WAF blocked it, and the in-process monitor went dark

An attacker IP, routed through a compromised VPS, hit /wp-login.php 321 times in 91 seconds. The site's edge WAF terminated the requests at the HTTP layer before WordPress's authentication code ran. From inside the application, the login hook never fired, no failed-auth event was emitted, and no rule on those events had anything to evaluate. The attack happened, was correctly blocked, and produced a 12-minute silence at the application layer.

Two views side-by-side told the actual story: at the access-log layer, 92 HTTP 503s and 311 HTTP 499s from one IP against /wp-login.php; at the application layer, near-zero failed authentications during the same window. When the first is large and the second is empty, the WAF is doing the work, and that's the layer the attack story has to be read from.

This is the consistent edge case for application-layer behavioral monitoring: the harder the site is secured at the edge, the less an in-process monitor can say about what hit it. The operator wired the WAF's block-event hook into the same monitoring layer as the application signals, so future events flow into one place regardless of where they were stopped.

The seven above are not your worst ones

Find out what your site is quietly doing.

Install the WordPress plugin or the Drupal module. Within minutes you'll see the operational state of your site, and within hours you'll know whether any of the patterns above are running on it.

Free to try on one site. Cancel anytime. No credit card.

Logystera Logystera
Behavioral monitoring for the systems your team operates. Read operational state, get told when behavior changes, with the evidence attached. Current integrations: WordPress and Drupal.
Copyright © 2026 Logystera. All rights reserved.