Yaamlabs
Supply chain

cPGuard update hijack: check servers, then rotate secrets

A stolen publishing key let attackers push a root script through cPGuard updates to about 2,950 Linux servers. How to check yours and what to rotate.

By Yaali. November 7, 2026, 6 min read, Supply chain, Threat intel, Resilience.

Cover illustration on a plain navy gradient, with the Yaamlabs logo and the text: cPGuard's own updates ran a root backdoor, about 2,950 servers ran the fake update

On November 2, 2026, an attacker used OPSSHIELD's own update system to push a malicious script to servers running cPGuard, the company's security suite for cPanel, DirectAdmin and standalone Linux web servers. The fake releases were numbered 5.88.12 through 5.88.19. cPGuard agents fetched and ran them as root, and OPSSHIELD estimates about 2,950 customer servers executed the script.

The script copied password hashes, root SSH keys, the MySQL root password, root's shell history and cloud storage keys, and left a hidden root shell behind. Updating cPGuard removes the backdoor files. It does nothing about the credentials that were already copied, so any host that installed one of those builds needs its secrets rotated, as do the other systems those secrets open.

Timeline of the cPGuard compromise, from a fake trial account on November 1 to fake updates running as root on about 2,950 servers on November 2, with the data taken from OPSSHIELD and from customer servers

How it works

cPGuard runs an agent on each server that polls OPSSHIELD's update storage and installs new releases automatically, with root privileges, because it has to manage firewall rules and scan every account's files. Whoever can publish to that storage can therefore run code as root on every connected server, with no login to the servers themselves.

According to OPSSHIELD's disclosure, the attacker started on November 1 by registering a customer account under a false identity and ordering a free cPGuard trial, which let them watch how the agent talks to the licensing system. They then sent crafted requests to callback pages on the billing portal and gained command execution on the combined billing and licensing server. From there they took the access key used to upload releases, and between 02:04 and 02:09 UTC on November 2 they uploaded the eight fake versions.

OPSSHIELD has not confirmed which request gave the attacker code execution on the billing server. It has patched two candidate entry points and is still reviewing its code and vendor components, so the root cause is open.

The payload was a short shell script. It read /etc/shadow and /etc/passwd, everything under /root/.ssh (private keys, authorized_keys, known_hosts), the MySQL root credentials in /root/.my.cnf, root's shell history and cloud storage keys in /root/.s3cfg. It packed them into /var/tmp/.cpg91511/loot.tgz and uploaded the archive to OPSSHIELD's licensing server under a compromised account, where the attacker could collect it later. It also planted a hidden root shell at /var/tmp/.cpg91511_sh and a scheduled task at /etc/cron.d/i93677 with its files in /var/tmp/.i93677/.

What attackers are doing

Servers installed the fake update between 02:08 and 03:20 UTC, roughly 70 minutes. A server where cPGuard was offline or did not poll in that window did not receive it, OPSSHIELD says. The company detected the compromise within 12 hours of the fake versions going out.

Its preliminary count is that the attacker retrieved 32 of the collected archives, each from a different customer server. That number covers confirmed downloads only. Every one of the roughly 2,950 servers that ran the script should be treated as exposed, because the archives sat for hours on a server the attacker could reach. For a smaller set of servers, OPSSHIELD may confirm that the attacker also logged in by hand.

The attacker also took records for about 7,900 OPSSHIELD customer accounts (name, company, postal address, email and a bcrypt hash of the billing portal password) and copied three of OPSSHIELD's cloud servers. OPSSHIELD has revoked the stolen upload key and its cloud API tokens, replaced SSH keys and passwords across its servers, is reissuing every cPGuard license key pair and is rebuilding its billing, licensing and management servers from clean images. Nobody has attributed the attack.

What to do

1. Find out whether a server installed a bad build. On every cPGuard host, run:

grep 'Successfully updated' /opt/cpguard/logs/install_log

Any line for 5.88.12 to 5.88.19 means the server is in scope, even if it now runs a clean version. A missing or truncated log does not clear a server; if you cannot show it was offline on November 2 between 02:08 and 03:20 UTC, treat it as in scope.

2. Look for the artifacts before you update. ls -ld /var/tmp/.cpg91511_sh /var/tmp/.cpg91511 /var/tmp/.i93677 /etc/cron.d/i93677, and search for cpguard-v58812-i91511*.sh. If they exist, copy them somewhere safe as evidence. Updating deletes them, so their absence afterwards proves nothing.

3. Update. Run cpgcli update --start, then cpgcli --version. Sources differ on the minimum: OPSSHIELD's first advisory named 5.88.25, and its later disclosure says 5.88.26 removes the hidden root shell and also strips the OPSSHIELD support-access keys that had been added to some servers. A further update removes the scheduled task. Take the newest release and confirm the three paths above are gone.

4. Rotate what was taken, on every in-scope server, working from a trusted recovery environment where you can:

  • passwords for root and every other local account that has one, plus the same passwords anywhere they were reused;
  • the MySQL or MariaDB root password and any database passwords stored in /root/.my.cnf;
  • S3 access keys, DigitalOcean tokens and anything in /root/.s3cfg;
  • every password, API key or token visible in root's shell history (read it; people type secrets into commands);
  • SSH key pairs under /root/.ssh. Remove the old public keys from every host that trusted them, and review authorized_keys here for entries you did not add.

Treat any machine reachable with those SSH keys as exposed until its keys are replaced.

5. Look for follow-on access. Check for new local users, unfamiliar SSH keys, new services or cron jobs, and outbound connections you cannot explain. If OPSSHIELD confirms the attacker logged in manually, rebuild from a backup taken before November 1. OPSSHIELD does not currently recommend a routine rebuild for other servers but says that advice may change.

6. Reset your OPSSHIELD billing portal password and turn on two-factor login, whether or not your servers were online during the window.

Root agents with automatic updates

Security agents get root and automatic updates so they can react fast, which makes the vendor's publishing pipeline part of your attack surface. In this case a trial account and a billing callback led to that pipeline in less than a day. It is the same pattern as the AOMEI Backupper update hijack last month.

Two controls limit the damage next time. Keep reusable secrets off hosts that run third-party root agents: database root passwords in /root/.my.cnf and cloud keys in dotfiles are exactly what this script went for. And alert on new files in /etc/cron.d and hidden files in /var/tmp, which would have flagged this payload on the first server it touched.

If you run hosting servers and want help scoping which hosts and keys this touched, our security operations team can do the triage and log review, and our safeguarding and hardening work moves secrets off the box. Open the chat and Yaali, our AI agent, will pass your question to an engineer.


Sources: Help Net Security, The Hacker News, SecurityWeek, WebHosting.Today, Windows FAQ, The Hacker Wire.

Read next

Back to the blog, or tell us about your system in the chat. Yaali, our AI agent, answers first and brings in an engineer.