Security Hole Cpanel – Wp-tool-kit: Deeper Look…🤦♂️
I run security audits regularly. I’ve seen misconfigurations, oversights, and the occasional lazy shortcut. What I found in cPanel’s WordPress Toolkit is unbelievable…
This doesn’t appear to be a bug. This is a deliberate architectural decision that gives unauditable code unrestricted root access to your server. By default. Without your consent. 😮🤦♂️
Millions of production servers are running this right now.
Finding #1: Passwordless Root Access — Deployed Automatically
Open this file on any cPanel server running WordPress Toolkit:
cat /etc/sudoers.d/48-wp-toolkit
Here’s what you’ll find:
wp-toolkit ALL=(ALL) NOPASSWD:ALL
Defaults:wp-toolkit secure_path = /sbin:/bin:/usr/sbin:/usr/bin
Defaults:wp-toolkit !requiretty
NOPASSWD:ALL
The wp-toolkit user can execute any command as root without a password. No restrictions. No whitelisting. Complete access to everything.
You didn’t enable this. You weren’t asked. It’s baked into the RPM install script:
rpm -q --scripts wp-toolkit-cpanel 2>/dev/null | grep -A 20 "preinstall scriptlet"
Every time WP Toolkit is installed or updated, this sudoers file gets created. Automatically. Silently.
Finding #2: It’s Actively Executing Root Commands
This isn’t sitting dormant. It’s running. Right now. On your server.
grep wp-toolkit /var/log/secure | tail -20
Here’s what I found in logs that made me dig deeper….
Feb 28 12:11:17 sudo[1911429]: wp-toolkit : USER=root ; COMMAND=/bin/cat /usr/local/cpanel/version
Feb 28 12:11:17 sudo[1911433]: wp-toolkit : USER=root ; COMMAND=/bin/sh -c 'whmapi1 get_domain_info --output=json'
Feb 28 12:11:18 sudo[1911442]: wp-toolkit : USER=root ; COMMAND=/bin/sh -c 'whmapi1 listaccts --output=json'
Look at that pattern: /bin/sh -c '...'
Arbitrary shell commands. As root. Constant execution.
Finding #3: You Cannot Audit What It’s Doing
I wanted to see what these scripts actually do. Here they are:
ls /usr/local/cpanel/3rdparty/wp-toolkit/scripts/
cli-runner.php
execute-background-task.php
read-files.php
write-files.php
transfer-files.php
Read those filenames again:
read-files.php— reads files as rootwrite-files.php— writes files as roottransfer-files.php— moves files as rootexecute-background-task.php— executes tasks as root
So let’s look at the source code:
file /usr/local/cpanel/3rdparty/wp-toolkit/scripts/*.php
cli-runner.php: data
execute-background-task.php: data
read-files.php: data
write-files.php: data
transfer-files.php: data
They’re not identified as PHP files. They’re data.
Because they’re ionCube encoded:
head -5 /usr/local/cpanel/3rdparty/wp-toolkit/scripts/cli-runner.php
<?php
// Copyright 1999-2025. Plesk International GmbH. All rights reserved.
// PLESK://PP.2500101/C4OLIU+C...
@__sw_loader_pragma__('PLESK_18');
Binary encoded. Obfuscated. The source code is hidden.
You cannot read what these scripts do. You cannot audit them for vulnerabilities. You cannot verify they’re secure.
But they have root access to your entire server.
Finding #4: This Is Official Code — Verified and Signed
I wanted to be absolutely sure this wasn’t some compromise or modification. So I verified it:
rpm -qi wp-toolkit-cpanel | grep -E "Signature|Vendor"
Signature : RSA/SHA512, Wed 14 Jan 2026 05:56:56 PM UTC, Key ID ba338aa6d9170f80
Digitally signed by cPanel. Official package.
rpm -V wp-toolkit-cpanel 2>&1 | head -10
All scripts match the official package. No modifications. No tampering.
The script headers explicitly state:
// Copyright 1999-2025. Plesk International GmbH. All rights reserved.
// This is part of Plesk distribution.
@__sw_loader_pragma__('PLESK_18');
This is Plesk’s WordPress Toolkit, distributed through cPanel’s official repository, digitally signed, running on millions of servers worldwide.
Finding #5: It Restores Itself… Every Night 🤦♂️
So I removed the sudoers file. Problem solved, right?
Nope.
There’s a cron job:
cat /etc/cron.d/wp-toolkit-update
This runs daily at 1 AM (with random delay) and executes:
yum -y update wp-toolkit-cpanel
When the package updates, the preinstall script runs. The preinstall script recreates /etc/sudoers.d/48-wp-toolkit.
Your fix gets silently undone. Every night. Automatically.
So removing the sudoers file alone doesn’t work. You have to disable the cron too, or you’ll wake up tomorrow with the same problem.
So….
cPanel ships WordPress Toolkit with:
| What They Ship | What It Means |
|---|---|
NOPASSWD:ALL sudo access |
Unrestricted root access, no authentication |
| Deployed automatically | No consent, no warning, no opt-in |
| ionCube-encoded scripts | Source code hidden, cannot be audited |
| Scripts that read/write/execute | Complete filesystem and command access |
| Digitally signed official package | This is intentional, not a compromise? |
| Nightly auto-update cron | Restores sudo access if you remove it |
| No security scanner detection | Flying under the radar on millions of servers |
This is a “trust us” security model:
- “Trust us with passwordless root access”
- “Trust us with code you can’t read”
- “Trust us that we got it right”
- “Trust us that attackers won’t find a way in”
On production servers. Hosting customer data. Running businesses.
The Attack Path
This is straightforward:
- Any vulnerability in WP Toolkit that allows command injection
- Payload reaches one of the encoded PHP scripts
- Script executes as
wp-toolkituser - User runs
sudo— no password needed - Complete server compromise
And because the scripts are encoded, you will never see the vulnerability coming. You cannot audit code you cannot read.
Check Your Server Right Now
# Check if the sudoers file exists
cat /etc/sudoers.d/48-wp-toolkit
# Check if auto-update cron is enabled
cat /etc/cron.d/wp-toolkit-update
# Verify scripts are encoded
file /usr/local/cpanel/3rdparty/wp-toolkit/scripts/*.php
# See what root commands are being executed
grep wp-toolkit /var/log/secure | grep COMMAND | tail -20
# Verify this is the official signed package (not tampered)
rpm -qi wp-toolkit-cpanel | grep -E "Signature|Vendor"
# Confirm scripts match official package
rpm -V wp-toolkit-cpanel 2>&1 | head -10
How to Fix It
Important: You need to do BOTH steps. Removing the sudoers file alone doesn’t work — the nightly cron will recreate it.
Step 1: Disable the Auto-Update Cron (Do This First)
# Disable the nightly auto-update cron
mv /etc/cron.d/wp-toolkit-update /etc/cron.d/wp-toolkit-update.disabled
# Verify it's disabled
ls -la /etc/cron.d/wp-toolkit-update 2>/dev/null || echo "✓ Auto-update disabled"
Step 2: Remove or Harden the Sudoers File
Option A: Remove it completely (Recommended)
rm /etc/sudoers.d/48-wp-toolkit
Most WordPress management doesn’t require root. If something specific breaks, address it then with a scoped solution. The risk is not worth the convenience.
Option B: Whitelist specific commands (Advanced)
If you need WP Toolkit automation, replace blanket access with specific commands:
cat << EOF > /etc/sudoers.d/48-wp-toolkit
# WP Toolkit - hardened configuration
wp-toolkit ALL=(ALL) NOPASSWD: /usr/local/cpanel/3rdparty/bin/wp
wp-toolkit ALL=(ALL) NOPASSWD: /bin/chown
wp-toolkit ALL=(ALL) NOPASSWD: /bin/chmod
Defaults:wp-toolkit secure_path = /sbin:/bin:/usr/sbin:/usr/bin
Defaults:wp-toolkit !requiretty
EOF
Always validate:
visudo -c -f /etc/sudoers.d/48-wp-toolkit
The Bottom Line
Plesk and cPanel are officially shipping ionCube-encoded PHP scripts that execute as root with NOPASSWD:ALL sudo access. The package is digitally signed. The scripts are verified. This is intentional. You cannot audit what these scripts do. You cannot review the source code. You cannot verify their security. Yet they have root over your server. They could covertly do anything….
It would seem this is deployed by default. On every cPanel server running WordPress Toolkit. No security scanner flags it. Not even a “oh hey, this could be a problem for you but this is how we did it”…
Check yours today.
