Home/ Blog/ Security news/ Article
Blog · Security news

Awesome Motive's WordPress CDN backdoor only fired for logged-in admins. Your scanner missed it.

OptinMonster, TrustPulse and PushEngage served a backdoor that ran only for logged-in WordPress admins, evading visitor scanners. How to scope and hunt it.

Central mast with one glowing thread reaching only the rooftops with lit windows

A malicious script rode three popular WordPress plugins into administrator dashboards last week, and the part worth your attention is not that it happened. It is how it hid. The code ran only when a logged-in administrator loaded a page, skipped anyone browsing as a normal visitor, and quit the moment it detected an automated browser. That one design choice defeats the two checks most site owners and shared hosts depend on: the visitor-perspective malware scan and the crawler. If your scanner reported clean this week, that is exactly the result the attacker engineered.

What actually happened

Researchers at Sansec found that JavaScript files served from Awesome Motive's content delivery network had been altered. Awesome Motive is one of the largest plugin makers on WordPress, and the tampered files belong to OptinMonster (more than a million active installs), TrustPulse, and PushEngage. The malicious code never lived on any victim's own server. It sat in the shared scripts that every site running those plugins pulls automatically, so a single edit at the source reached every downstream site at once. BleepingComputer reports the attacker reached the CDN by stealing API credentials from a separate Awesome Motive marketing server that ran an outdated copy of UpdraftPlus, a server the vendor says was not wired to production.

The exposure windows were short but not identical across the three plugins. The OptinMonster and TrustPulse files carried the payload for roughly 25 minutes late on June 12 (UTC). PushEngage stayed tainted longer, into June 13 by one account and June 14 by another. Treat the PushEngage tail as the wider one until you can confirm otherwise. The command channel, a domain dressed up to look like the chat vendor Tidio, had been registered back on April 28, so this was staged well ahead of the push.

Why your malware scanner showed clean

The payload checked who was looking before it did anything. It confirmed a logged-in administrator by reading wp-admin paths, the admin toolbar, and the wordpress_logged_in_ cookie. It exited if it saw a headless browser, a web driver, or a zero-size window. It also wrote a 24-hour throttle into localStorage so it would not fire twice and draw attention.

Read that as a targeting spec. A malware scanner that requests your pages as an anonymous visitor sees the clean branch. A crawler that renders the site in a headless browser hits the early exit. The only session that ever runs the hostile code is a real human admin with a valid cookie, which is the one session your external scanning almost never replays. This is why a green scan result this week tells you nothing. The check and the threat never overlapped.

Scope by session, not by install base

The reflex after a plugin compromise is to list every site running the plugin and treat them as one population. That is the wrong denominator here. The payload only acted when an admin was logged in during the injection window, so the real blast radius is the overlap between two sets: sites running the affected plugins, and admin sessions that were live during those minutes.

For a single site owner that is a yes or no question. For a host or an agency carrying hundreds of tenants it is the difference between a frantic all-sites rebuild and a targeted hunt. Pull your access logs and find which sites had an authenticated wp-admin request between roughly 22:17 and 22:42 UTC on June 12, and across the longer PushEngage window. Those are the sites to treat as compromised. The rest got lucky on timing, though they should still confirm the artifacts below are absent.

What to hunt for tonight

The cleanup is not a plugin update. Once the script ran with an admin's privileges it left durable backdoors that survive a fix at the CDN. Hunt for these directly:

  • Rogue admin users. Look for an account named developer_api1 or anything matching dev_xxxxxx. The script tried four ways to create one, from the registration form to the REST API users endpoint, and it recognized "user already exists" responses in about twenty languages, so do not assume a non-English site was spared.
  • Hidden plugin directories. Check the filesystem for wp-content/plugins/content-delivery-helper or wp-content/plugins/database-optimizer. The backdoor ships under both names with identical behavior and hides itself from the dashboard plugin list, the /wp/v2/plugins REST endpoint, the update checker, and the recently-active list. You will not see it in wp-admin. You will see it on disk.
  • Outbound calls to the fake Tidio domain used for exfiltration and tasking.

Note what does not work here. The hidden plugin regenerates its own ZIP on every request, so its file hashes keep changing and any detection keyed on a known-bad hash slides right past it. File-integrity monitoring that only flags hash drift will fire without telling you what changed, or miss it entirely if the baseline was captured after infection. The reliable signals are structural, not cryptographic: a new administrator account, a plugin directory that exists on disk but not in the dashboard, and a server-side scan run with filesystem access rather than over HTTP.

If an admin was logged in during the window, assume the attacker had unauthenticated code execution on that site and act like it. Remove the rogue accounts and the hidden plugin, then rotate everything the session could touch: admin passwords, plugin and CDN API keys, database credentials, and the WordPress salts in wp-config.php. Patching the plugin without rotating leaves the front door propped open.

The real lesson: a vendor's CDN is unpinned code in your admin session

Strip away the WordPress specifics and this is the same move that hit Polyfill.io: take over a script that millions of sites load from a trusted central source, and you inherit the privileges of whoever loads it. The twist here is the target. Instead of skimming card numbers from shoppers, this payload waited for the one visitor who can install plugins and create users.

You cannot defend a mutable CDN script with subresource integrity, because an SRI hash pins a file that is meant to change and a vendor that ships updates needs it to change. So every plugin that loads JavaScript from its maker's CDN is a remote code dependency running inside your admin session, and you are trusting that vendor's build pipeline and credential hygiene as if they were your own. They usually are not. We have written before about how a trusted internal service becomes the breach path, whether that is an ERP patch service turned into the entry point or the login stack itself being backdoored. The Awesome Motive incident is the same trust-axis problem wearing a plugin's clothes.

The practical takeaway is the same one that applied to the Ivanti Sentry cleanup: the patch closes the hole, it does not undo what came through it. Inventory which third-party scripts run with admin privileges on the sites you operate, decide which vendors you would actually trust with code execution in your dashboard, and accept that one of those CDNs will eventually serve you something you did not write. Plan the hunt for that day now, while it is someone else's incident.

Frequently asked questions

Which WordPress plugins were affected by the Awesome Motive CDN attack?

OptinMonster, TrustPulse, and PushEngage were affected, all made by Awesome Motive.

The malicious code was injected into JavaScript those plugins load from Awesome Motive's content delivery network, not into the plugins installed on each site. OptinMonster alone runs on more than a million sites.

How do I know if my WordPress site was backdoored?

Check for an administrator account named developer_api1 or matching dev_xxxxxx, and for plugin folders content-delivery-helper or database-optimizer on disk under wp-content/plugins.

The hidden plugin does not appear in the dashboard, so inspect the filesystem and user table directly rather than the admin screens.

Why did my malware scanner not detect this WordPress attack?

The payload ran only for logged-in administrators and exited for ordinary visitors, headless browsers, and automated scanners.

A scanner that loads your pages as an anonymous visitor sees only the clean code path, so a passing scan does not mean the site is unaffected.

What should I do if an admin was logged in during the attack window?

Assume the attacker gained code execution and treat the site as compromised.

Remove the rogue admin account and hidden plugin, run a server-side malware scan, then rotate admin passwords, plugin and CDN API keys, database credentials, and the WordPress salts in wp-config.php.

Was WordPress core compromised in the Awesome Motive incident?

No. WordPress core was not involved, and the affected plugins' own code and update servers were not altered.

Attackers compromised a separate Awesome Motive server, stole CDN credentials, and changed the JavaScript files served from the CDN to many sites at once.

Ready to meet the Guardians?

Deploys fast - agentless for monitoring and cloud, a lightweight agent for deep endpoint security. Just Suriq, standing watch.