A single hidden file on one WordPress site can quietly take over an entire server, and the trigger is a command your team might run without thinking. Running WP-CLI as root with --allow-root isn’t standard practice, but as recent telemetry shows, it does still happen in real hosting setups: cron jobs, control-panel automation, deployment scripts. It exists to avoid the friction of dropping to each site’s own system user. It is also the door an attacker walks through. Wherever that pattern is in place, it is tempting to treat a read-only command such as wp plugin list or wp user list as harmless. It is not. Any command that boots WordPress unconditionally executes every must-use plugin (wp-content/mu-plugins/*.php) at load time, before a single line of the command’s own logic runs. So if an attacker drops a malicious .php file into one account’s mu-plugins/, the next time an operator runs any WordPress-loading command as root with --allow-root (even just a harmless wp plugin list), the full payload is loaded. We have seen the same pattern across different hosting environments running similar automation, where everyday WordPress maintenance workflows can quietly become a privilege-escalation path.
This is not theoretical
We are not describing a lab curiosity. Imunify360 telemetry has observed this exact exposure in the wild (must-use-plugin droppers sitting on servers whose operators run WP-CLI as root) across multiple hosting environments. The CloudLinux research team is engaging the affected providers directly with remediation guidance and safer operational practices, which is a large part of why we are publishing this. The pattern is common enough, and quiet enough, to be worth a public warning.

The setup operators actually use
Control panels and maintenance scripts frequently loop over every site on a server as root:

The intent looks read-only and safe. The reality is that each iteration fully bootstraps that customer’s WordPress, and runs their mu-plugins code as root.
And it is far from just plugin's list. In our telemetry we see a broad spread of these root invocations across real hosts for status checks, cache and object-cache maintenance, config reads, content and user listings:

Why “read-only” is a myth here
WordPress loads must-use plugins on every boot unconditionally. They have no activation switch and no hook; WordPress simply includes them. From wp-settings.php:

No capability check, no is_admin() gate, no hook. Any top-level statement runs the instant WordPress starts, a web request, cron, or CLI alike.
👇 Take these as examples the following inoffensive commands an operator fires off without a second thought:
| Command | Category | MU-plugin runs? |
|---|---|---|
wp plugin list | Read-only listing | 💥 Yes |
wp user list | Read-only listing | 💥 Yes |
wp post list | Read-only listing | 💥 Yes |
wp option get | Read-only listing | 💥 Yes |
wp option update | Write | 💥 Yes |
wp cache flush | Maintenance | 💥 Yes |
wp rewrite flush | Maintenance | 💥 Yes |
wp cron event run | Maintenance | 💥 Yes |
wp search-replace | Maintenance | 💥 Yes |
wp plugin update --all | Maintenance | 💥 Yes |
| …and many others | Anything that boots WordPress | 💥 Yes |
Note:
--skip-pluginsdo NOT skip must-use plugins.This is expected, documented behaviour, still present as of the latest WP-CLI release (v2.12.0) — see WP-CLI PR #2480.
Patient zero: how the first Malware crafted MU-plugin lands
The whole chain starts at the level of a single account, never root, no LPE, the attacker only needs to write one PHP file into one site’s mu-plugins/. The usual ways in are ordinary:
- A compromised admin account: phished, brute-forced, or reused credentials.
- A hijacked session: a stolen
wordpress_logged_incookie is enough; no password required. - An abused file-manager plugin: With WP File Manager installed, the built-in file browser is all it takes: so a plain admin, using nothing but the WP File Manager GUI’s documented file operations (New Folder ->
mu-plugins/, New File -> the payload), plants an auto-executing MU-plugin. (Older versions also allowed unauthenticated attackers to upload arbitrary files – CVE-2020-25213). - A rogue admin written straight to the database: More sophisticated malware inserts its own hidden administrator row for durable persistence, then uses that account to drop the MU-plugin.
Malware in the wild: the scope-backup-bit family
Imunify360 telemetry caught a recent campaign with this exact mechanism being used as a distribution channel by a self-spreading, obfuscated mu-plugin family. On a single monitored server it found thousands of must-use-plugin files spread across dozens of tenant accounts.
Indicators of compromise
Family: scope-backup-bit (obfuscated mu-plugin backdoor)
SHA-256: 724e2ee968b0a19de5f6f90350c644cce0d4e889aa641d59ce1a931fe908ef3b
Aliases: scope-backup-bit.php, elementor-safe-mode.php,
async-environment-manager.php, grid-shield-tag/…,
pulse-compiler-hq.php (+ fresh, rotating aliases)
Analyzed: "Scope Extension Jet" v4.5.8 (same family)
SHA-256: 8af2df58d53ef4973b3a1d8e3cff029a618f85eadd1a0a3c35be7170891fcb50
Detection: SMW-SA-2038640-php.bkdr.obf-2
Artifacts: owner=0 files in wp-content/mu-plugins/; root-owned mu-plugins/
directory.
Why this matters for hosts specifically
- One tenant compromises all tenants. The malware only needs write access to one account’s
mu-plugins/. Your root automation does the privilege escalation for the attacker, on schedule silently. - It’s silent.
mu-pluginsdon’t appear in the standard Plugins list and aren’t disabled by--skip-plugins. Operators rarely look there.
Defense in depth with Imunify360
The primary recommendation stands on its own: disable --allow-root wherever possible in automation and control panels, and run WP-CLI under each site’s own user. Imunify360 provides multiple layers of protection that help stop this type of attack at different stages.
- RASP layer catches the malware at runtime and block it.
- Web Application Firewall (WAF) blocks the web-facing vectors droppers use to land in
mu-plugins/in the first place. - Imunify Security (WordPress plugin) complements the WAF from inside WordPress, adding enhanced coverage for known plugin and theme CVEs.
- Malware scanning with heuristic detection flags obfuscated families like
scope-backup-biteven as they rotate filenames (this campaign is detected asSMW-SA-2038640-php.bkdr.obf-2).
🔒 Imunify360 integrates natively with the CloudLinux ecosystem with CloudLinux OS, CageFS mitigation.


Comments