OpsShield's hijacked cPGuard updates (5.88.12–5.88.19) stole root secrets; here's how to check and clean your clients' servers.
The software installed to keep burglars out of Linux web servers spent 70 minutes letting one in. On 2 November 2026, between 02:08 and 03:20 UTC, OpsShield says its cPGuard update channel delivered a fake update that ran as root, copied password hashes, SSH keys and the database root password, and left a backdoor shell on about 2,950 customer servers.
cPGuard is a security suite for cPanel, DirectAdmin, Plesk and standalone Linux servers, and it updates itself on a schedule. If you look after hosting servers for clients, it may be on some of them.
The cPGuard supply chain attack hijacked the product's own update channel; it was not a bug in the product. OpsShield's advisory says an unidentified attacker "used compromised credentials to gain unauthorized access" to its update CDN on 2 November 2026 and pushed a malicious script as cPGuard 5.88.12 through 5.88.19. How the credentials were stolen is still under investigation.
OpsShield's longer disclosure fills in the rest. Between 1 and 2 November the attacker registered a customer account, got into the billing portal at manage.opsshield.com and gained command execution on that server. The advisory gives 02:06 UTC as the start and says OpsShield caught it within 12 hours; the disclosure narrows the push to about 70 minutes, 02:08 to 03:20 UTC.
Think of a locksmith whose van was stolen: every customer who let "the locksmith" in that morning handed over their keys.
The script collected the server's most valuable secrets and uploaded them to OpsShield's own licensing server, where the attacker picked them up. The disclosure lists:
/etc/shadow and /etc/passwd (every local password hash)/root/.my.cnf, the MySQL root password where present/root/.s3cfg cloud storage keys, on a few serversIt also left a scheduled task at /etc/cron.d/i93677 and a setuid-root shell at /var/tmp/.cpg91511_sh: anyone able to run that file got root.
OpsShield's preliminary estimate is that the attacker retrieved 32 collected files, "each corresponding to a customer server", and it warns this is not the number of affected servers. BleepingComputer reported that an OpsShield spokesperson put the affected count at 2,946 servers.
Read the cPGuard install log first, then look for the files the fake update left. OpsShield warns that a missing log, or files already gone, does not prove a server is clean. Run these as root; the loop after step 5 covers a whole fleet.
D=/root/ir-cpguard-$(date +%Y%m%d%H%M); sudo mkdir -p "$D"
sudo cp -a /opt/cpguard/logs /etc/cron.d /root/.ssh /root/.bash_history /root/.s3cfg /root/.my.cnf /var/tmp/.i93677 /var/tmp/.cpg91511 /var/tmp/.cpg91511_sh "$D"/ 2>/dev/null
sudo find "$D" -type f -exec sha256sum {} + | sudo tee "$D.sha256"
sudo grep 'Successfully updated' /opt/cpguard/logs/install_log
sudo ls -la /etc/cron.d/i93677 /var/tmp/.i93677 /var/tmp/.cpg91511 /var/tmp/.cpg91511_sh
sudo ls -la /etc/cron* /var/spool/cron/*
sudo find /tmp /var/tmp /dev/shm -xdev -perm -4000 -type f -ls
KNOWN-BAD is a hash match, NAME-MATCH a same-named variant; both are hits:findmnt -rn -t ext4,xfs,btrfs -o TARGET | while read -r m; do
sudo find "$m" -xdev -type f -name 'cpguard-v58812-i91511*.sh' -exec sha256sum {} +
done | awk 'BEGIN{split("2c2acd988da531d133d0e17f245c49bf15781278f837543d18c95e8410eabd38 ffd7a47f65fa1244429baa936ae94be54676b53d2f88bc39564f24e22011de8a d73919af84bf46de941db85e27fd1abc65701ef9ce6cf33bb27c5397f4a41c26 6add0201e9a3d02de772d561d05e0da86eb1c538686753b7adcc3aedf7366f77",h," ");for(i in h)bad[h[i]]=1} {print (($1 in bad)?"KNOWN-BAD ":"NAME-MATCH ") $0}'
94.183.188.91 and cPGuard/5.88.11 without saying they touched customer servers, so a hit means dig further:sudo find /var/log /usr/local/apache/domlogs -type f -exec zgrep -lE '94\.183\.188\.91|cPGuard/5\.88\.11' {} + 2>/dev/null
To run steps 1 to 5 across a client fleet, save them as cpguard-check.sh and loop over a list of all the Linux servers you manage, including ones you think never had cPGuard:
for h in $(cat cpguard-hosts.txt); do echo "== $h"; ssh root@"$h" 'test -d /opt/cpguard && bash -s || echo "no cPGuard"' < cpguard-check.sh; done
Backups matter too. A snapshot taken after 02:08 UTC on 2 November can bring the backdoor and the old secrets back, which is why OpsShield's rebuild advice names a clean backup taken before 1 November.
Updating removes the backdoor, but the stolen secrets keep working until you change them. On any server the checks flagged:
sudo ls -d /root/ir-cpguard-* before deleting anything.sudo cpgcli update --start, then confirm sudo cpgcli --version shows 5.88.26 or later. The cPGuard changelog says 5.88.25 patched the compromised update and 5.88.26 revoked OpsShield support access where it was enabled.sudo rm -rf /etc/cron.d/i93677 /var/tmp/.i93677 /var/tmp/.cpg91511 /var/tmp/.cpg91511_sh
for u in $(sudo awk -F: '$2 ~ /^\$/ {print $1}' /etc/shadow); do echo "== $u"; sudo passwd "$u"; done
/root/.my.cnf by hand. Elsewhere, use MariaDB's ALTER USER and update /root/.my.cnf to match. Then run mysql -uroot -p -e 'SELECT 1' with the old password and confirm "Access denied".sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'NEW-LONG-PASSWORD';"
sudo ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519_new
OLD=$(sudo sh -c "ls /root/ir-cpguard-*/.ssh/id_*" | grep -v '\.pub$' | head -1)
for h in $(cat cpguard-hosts.txt); do sudo ssh -o BatchMode=yes -o IdentitiesOnly=yes -i "$OLD" root@"$h" true 2>/dev/null && echo "$h STILL TRUSTS OLD KEY"; done
sudo sh -c "grep -niE 'pass|token|secret|key' /root/ir-cpguard-*/.bash_history"
sudo sh -c "s3cmd -c /root/ir-cpguard-*/.s3cfg ls"
If OpsShield told you the attacker logged in to a server by hand, its advice is to rebuild from a clean backup taken before 1 November.
A pentest won't tell you whether a script ran in /var/tmp on 2 November; the checks above do that. KinoSec answers your client's next question: what could someone holding those secrets still reach? It runs an autonomous pentest of each client's external network and web apps, maps which logins and services face the internet (SSH, the cPanel and WHM login pages, database ports), finds the weaknesses, shows how they chain together and writes it up with remediation. For clients with Active Directory, it tests that side too. Run it after the rotation and you hand your client a report instead of a promise.
Yes. OpsShield says an attacker used stolen credentials to reach its update CDN and, on 2 November 2026, pushed malicious cPGuard updates 5.88.12 through 5.88.19 that stole root secrets and planted a backdoor. OpsShield counts about 2,950 customer servers that ran the fake update.
First, as root, run grep 'Successfully updated' /opt/cpguard/logs/install_log and look for any 5.88.12 to 5.88.19 entry. Second, run ls -la /etc/cron.d/i93677 /var/tmp/.cpg91511_sh to look for the dropped files. Third, hash any cpguard-v58812-i91511*.sh file against the four SHA-256 values in OpsShield's indicator table; a missing log or missing files does not prove a server is clean.
Updating to 5.88.25 or later removes the known backdoor and staged files, but it does not undo the theft. Local passwords, root's SSH keys, the database root password and secrets in root's shell history must all be changed. The cPGuard changelog says 5.88.26 also revokes OpsShield support access.
No; the install log and file checks do that. An autonomous pentest such as KinoSec shows what an attacker could still reach on each client's external network, web apps and Active Directory once secrets have leaked, and gives you a report to hand your client.