The Security Update Was the Break-In

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.

TL;DR

  • What happened: an attacker used stolen credentials to reach OpsShield's update CDN and pushed malicious cPGuard 5.88.12–5.88.19 updates on 2 November 2026 that stole root secrets and planted a setuid-root shell.
  • Are your clients exposed? A server counts as exposed if its cPGuard install log shows a 5.88.12–5.88.19 update, or cPGuard was online between 02:08 and 03:20 UTC, per OpsShield.
  • What to do: update to cPGuard 5.88.26, delete the backdoor files, then change local passwords, the database root password, root's SSH keys and any secrets in root's shell history.
  • Impact: OpsShield counts about 2,950 customer servers that ran the fake update and about 7,900 billing-portal accounts copied, according to its disclosure.

What happened in the cPGuard supply chain attack?

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.

What did the cPGuard backdoor steal?

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's SSH keys and shell history (which often holds typed passwords and tokens)
  • /root/.my.cnf, the MySQL root password where present
  • /root/.s3cfg cloud storage keys, on a few servers

It 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.

How do I check if cPGuard was compromised on my clients' 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.

  1. Preserve evidence before you clean anything:
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"
  1. Read the install history. Any line naming 5.88.12 to 5.88.19 means the server took the bad update, even if it now runs a fixed version:
sudo grep 'Successfully updated' /opt/cpguard/logs/install_log
  1. List the dropped files, all cron entries and setuid files in temp folders. Nothing unexpected should appear:
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
  1. Hash any copy of the fake update script on all local disks against the four SHA-256 values in OpsShield's indicator table. 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}'
  1. Search all logs, rotated ones included, for the attacker's IP and fake user agent. OpsShield lists 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.

How do I fix cPGuard and clean up?

Updating removes the backdoor, but the stolen secrets keep working until you change them. On any server the checks flagged:

  1. Preserve evidence first: confirm the step 1 copy and its hash file exist with sudo ls -d /root/ir-cpguard-* before deleting anything.
  2. Update cPGuard with 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.
  3. Delete the dropped files with the command below, then rerun check 3 and confirm all four paths report "No such file or directory".
sudo rm -rf /etc/cron.d/i93677 /var/tmp/.i93677 /var/tmp/.cpg91511 /var/tmp/.cpg91511_sh
  1. Change all local passwords. This loop finds the accounts with a password hash and prompts you, account by account, for a new one; afterwards a login with an old password must be refused:
for u in $(sudo awk -F: '$2 ~ /^\$/ {print $1}' /etc/shadow); do echo "== $u"; sudo passwd "$u"; done
  1. Change the database root password. On cPanel servers use WHM » Database Services » Change Database Root Password; cPanel's documentation says not to edit /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';"
  1. Replace root's SSH keys. Generate a new pair with ssh-keygen, install the new public key where root needs access and remove the old one. Then prove no server in your list still accepts the old private key from the evidence folder; the loop must print nothing:
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
  1. Rotate secrets from the shell history and cloud config. List candidates with the first command below, revoke them with the service that issued them, then confirm the old S3 keys fail (expect AccessDenied):
sudo sh -c "grep -niE 'pass|token|secret|key' /root/ir-cpguard-*/.bash_history"
sudo sh -c "s3cmd -c /root/ir-cpguard-*/.s3cfg ls"
  1. Reset the manage.opsshield.com billing password, as the disclosure asks of all customers, then confirm the old password is refused at the login page.

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.

Where KinoSec fits

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.

Frequently Asked Questions

Was cPGuard hacked?

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.

How do I check if cPGuard was compromised on my clients' servers?

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.

Does updating to cPGuard 5.88.25 fix it?

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.

Can an autonomous pentest find the cPGuard backdoor?

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.