OpsShield says a fake cPGuard update ran as root on about 2,950 servers; its two notices differ in places
OPSSHIELD says a fake cPGuard update was installed on customer servers between 02:08 and 03:20 UTC on 2 November, ran as root and copied credentials back. Its advisory and its later disclosure differ on the entry route, the window, the files taken and the counts.
By Parminder Kumar Sharma · LinkedIn · · 21 min read
72 minutes counted, about 70 claimed, and a log that runs to 12:46
OPSSHIELD's incident disclosure says its fake cPGuard update was installed by customer servers between 02:08 and 03:20 UTC on 2 November 2026, and elsewhere says it shipped the update for "about 70 minutes". The two printed times are 72 minutes apart (derived: this site subtracts them). The vendor's earlier advisory names eight affected versions, 5.88.12 to 5.88.19, and prints five example install log lines that run from 02:46:04 to 12:46:01 on 2 November, 9 hours 59 minutes 57 seconds apart (derived), on a clock the advisory says "may differ". Both pages can be true. Neither says how.
That is the first of several places where the vendor's two notices tell the story differently: how the attacker got in, how long the bad update was live, which versions are bad, which files were taken, how many servers are involved and whether to rebuild. Neither is wrong on its face. The disclosure is the later and fuller account, and the advisory itself says it "records our earlier findings". The facts moved as the investigation went on. What a defender needs is to work under the stricter of the two readings, and to know what neither notice establishes.
This briefing reads both notices in full on 4 November 2026 between 07:49 and 07:50 UTC, after reading the host's robots file (HTTP 404, so no restriction applies). Both pages were byte for byte the same as the copies saved at about 07:46 UTC that morning, with no new section and no later stamp, and BleepingComputer's article text was unchanged. The cPGuard changelog and the vendor's blog index were read the same morning. BleepingComputer's report is a secondary source, used only for the spokesperson's figure and for what the press was told. OPSSHIELD sells cPGuard, and the account of this incident is its own: a company writing in the middle of an investigation, which both notices say in words such as "provisional" and "preliminary". That is stated once here and not repeated as a charge.
A note on names. cPGuard is the product and OPSSHIELD the vendor (the page footer says OPSSHIELD LLP). "Hijack" is BleepingComputer's headline word. The vendor's own words are "unauthorized access", "update channel compromise" and "broke into". "Backdoor" is the word both the vendor and BleepingComputer use for the hidden root shell the fake update left behind. The product is used by hosting firms and server administrators beside panels such as cPanel, DirectAdmin and Plesk, according to BleepingComputer; the vendor's page navigation lists the same panels.
The disclosure's own timeline, and the one step it cannot show
The disclosure's table runs from 15:38 UTC on 1 November to a notice on 3 November. In its words, the attacker registered as a customer, used that account to break into the billing and licensing server, took the keys used to publish updates and shipped a fake update. The diagram follows the table. Every card is OPSSHIELD's statement; the grey and amber cards are this site's arithmetic.
Disclosure timeline as printed (UTC), with this site's derived intervals. Read 4 Nov 2026.
| When (UTC) | What the disclosure prints | Derived by this site |
|---|---|---|
| 1 Nov, 15:38 | Attacker begins probing the billing portal | Start of the clock |
| 1 Nov, 16:34 | Registers a customer account under a false identity and orders a free cPGuard trial | 56 minutes after the first probe |
| 1 Nov, 21:17 | Installs the trial on their own server to study how the agent talks to the licensing system | 4 h 43 min after registering |
| 1 Nov, 21:40 to 21:51 | cPGuard flags and bans the attacker twice | 23 minutes after the install; the window is 11 minutes |
| 1 Nov, 22:50 | Crafted requests to the billing portal's callback pages | 59 minutes after the last ban |
| 1 Nov, 22:58 | Gains the ability to run commands on the billing and licensing server and starts collecting data | 8 minutes later |
| 2 Nov, 02:04 to 02:09 | Uploads a fake cPGuard update to update storage using a stolen access key | 3 h 06 min after command ability; a 5 minute window |
| 2 Nov, 02:08 to 03:20 | Agents install the fake update; it runs as root and copies sensitive files back | 72 minutes; the page says about 70 |
| 2 Nov, 02:13 | Attacker makes copies of three of OPSSHIELD's cloud servers | 4 minutes after the upload window closed |
| 2 Nov, no time | Stolen update key revoked; clean update 5.88.26 published | Not derivable |
| 3 Nov, no time | Entry point traced; notice published | Not derivable |
First probe to the start of the upload is 10 hours 26 minutes (derived). The vendor writes "about ten hours" and adds that attackers now use AI tools to read code and write tools quickly, so the speed "reflects that". That is the vendor's inference. The page prints no log, tool or artifact that shows AI use, and this briefing does not rely on it.
Two lines in the table need care. The disclosure says cPGuard flagged and banned the attacker twice between 21:40 and 21:51, and its next entry is at 22:50. Its list of actions includes "fixing cPGuard so temporary bans are enforced on nftables firewalls". The page does not say the second explains the first, so this briefing does not either. And the timeline says the entry point was traced on 3 November, while the text beside it says the vendor's logs "do not record the exact request that gave them access" and that two possible entry points were patched. The disclosure also says it has ruled out SSH, the control panel, FTP and API tokens. It names no vulnerability and no class of flaw, and neither does this briefing.
Stamps on the pages need the same care. The advisory is published 3 November and last updated at 3:19 AM IST, with sub updates at 2:42 AM and 3:17 AM IST. India Standard Time is UTC plus 5 hours 30 minutes, so those are 21:49, 21:12 and 21:47 UTC on 2 November (derived). The disclosure prints a date and no time. BleepingComputer's article carries 5:18 PM on 3 November at an offset of UTC minus 5 hours, which is 22:18 UTC, 24 hours 29 minutes 50 seconds after the advisory's last stamp (derived). So how far apart the two notices were published cannot be read from the pages, and whether the disclosure was out when BleepingComputer's spokesperson spoke of "preparing for a public announcement" is not stated.
Eight places the two notices differ, each as printed
1. Entry route. The advisory says an unidentified attacker "used compromised credentials to gain unauthorized access" to the update distribution infrastructure (CDN) and that the vendor is "investigating how the credentials were obtained". The disclosure says nothing about a CDN. It says the attacker registered a customer account, sent crafted requests to the billing portal's callback pages, gained command ability on the billing and licensing server, took the update publishing keys and uploaded the fake update to update storage with a stolen access key. The two are compatible if the stolen access key is the compromised credential. The disclosure answers the question the advisory left open, and then states its own gap: the exact request is not in the logs.
2. Where the stolen files went. The advisory says the script uploaded collected data to OPSSHIELD's own licensing server "under a compromised account" for the attacker to retrieve later. The disclosure says the script sent files to "a server the attacker controlled" and lists a URL pattern, files ending in _rx.php, as the endpoints that received the stolen data. Because the disclosure also says the attacker could run commands on the licensing server, one server can be both. The pages do not say that it is.
3. Versions, fix versions and the window. The advisory: versions 5.88.12 to 5.88.19 are affected, and "5.88.25 or later" includes the corrective update. The disclosure: the fake update was distributed for about 70 minutes, agents installed it between 02:08 and 03:20 UTC, and a clean update numbered 5.88.26 removes the hidden shell, with a follow up update removing a scheduled task. It prints no version range for the fake update, only the script name, which carries v58812. The advisory's example lines show five different versions installed at 02:46, 04:46, 08:46, 10:46 and 12:46, all at 46 minutes past the hour (derived observation); it does not say they come from one server. If they do, and the clock is UTC, the last line is 9 hours 26 minutes after the disclosure's window closed. The advisory calls its timestamps examples that "may differ", and the vendor labels the advisory as earlier findings. This briefing does not decide which window is right. The vendor's public changelog adds a third description. It dates 5.88.25 to 2 November 2026 with the note "Patched compromised update" and 5.88.26 to the same day with "Revoked support access to servers if it is enabled". Its entry before those is 5.88.11 on 22 October, and it lists none of 5.88.12 to 5.88.24. The page is a selection, not a full list of builds (it has 5.88.03 and 5.88.11 and nothing between), so that absence proves nothing. The advisory's last sub update, at 3:17 AM IST, also describes an update that removes OPSSHIELD support access keys. So the pages describe what 5.88.25 and 5.88.26 do in three ways. Whether 5.88.26 contains everything in 5.88.25 is not stated.
4. Detection time. The advisory: "We detected the attack within 12 hours of the launch of the updates in question." Twelve hours after the 02:06 UTC time the advisory gives for the attack is 14:06 UTC (derived), though the advisory counts from the launch of the updates and prints no time for that. The disclosure's timeline gives no detection time; its agent installs end at 03:20 UTC. BleepingComputer repeats the 12 hours. The advisory also says update checks run at intervals, so some servers may not have run the script, and that this timing "does not establish whether data was transferred".
5. What was collected. The advisory lists /etc/shadow and /etc/passwd, the root MariaDB or MySQL configuration, root shell history, and root SSH authorization and known hosts files. The disclosure lists the same and adds the whole of /root/.ssh (it says root SSH private keys, authorized keys and known hosts), /root/.my.cnf, and /root/.s3cfg cloud storage keys on a small number of servers. The advisory's collected list therefore omits private keys and cloud keys. Its own rotation advice does not: it says to replace SSH private keys under /root/.ssh, rotate S3 access keys and DigitalOcean tokens, and rotate secrets in root's shell history. So the gap is in what the vendor said was taken, not in what the advisory told a defender to replace. The advisory also says its list does not establish that every file was collected from every server.
6. What the update left behind, and where. Both pages name a hidden root shell at /var/tmp/.cpg91511_sh, which the disclosure describes in its indicator table as a setuid root shell. Beyond that they name different paths. The advisory names the collection directory /var/tmp/.cpg91511 and an archive inside it. The disclosure names a scheduled task at /etc/cron.d/i93677 and a directory /var/tmp/.i93677/ and says a follow up update removes the task. The advisory names one script file; the disclosure says there are four variants. The union of both lists is in the technical details below. The advisory adds that "The absence of these files after cleanup does not establish whether the script previously ran."
7. Counts. Three figures with three meanings, in the next section.
8. Rebuild. The advisory says OPSSHIELD is "not recommending a full server reset or operating-system rebuild as a routine response", calls that assessment "provisional", and says a rebuild may be appropriate if you find further signs of compromise or cannot establish integrity. The disclosure says that if the vendor told you the attacker logged in to your server by hand, rebuild it from a clean backup taken before 1 November, and that its own affected servers "are being rebuilt from scratch". It does not say how the vendor would tell you, or whether any customer server saw a manual login. The two positions do not contradict: one is the default, the other is the exception. They differ in how much a defender must prove before choosing.
Four figures, four meanings
The notices and the press carry four numbers. They count different things at different times. None is another's total, and this briefing does not add, subtract or rank them.
Counts on the three pages, with source, meaning and what each does not say. Read 4 Nov 2026.
| Figure | Source and time | What it counts | What it does not say |
|---|---|---|---|
| 32 files | Advisory, sub update 3 Nov 2:42 AM IST (2 Nov 21:12 UTC, derived) | Collected files the attacker retrieved from data uploaded to the licensing server, each matching a customer server | Called a preliminary estimate of confirmed retrieval, "not the total number of potentially affected servers" |
| About 2,950 | Disclosure, 3 Nov | Customer servers that ran the fake update | How many ran it for certain, or how many had files retrieved |
| 2,946 | A spokesperson, quoted by BleepingComputer, 3 Nov | Servers "affected and copied the information mentioned" | Whether it is the disclosure's figure rounded; the verbs differ |
| About 7,900 | Disclosure, 3 Nov | Billing portal accounts: name, company, postal address, email, bcrypt hash | Anything about customer servers; it is a different system |
The only arithmetic here is derived: 2,946 rounds to 2,950 at the nearest ten, so the disclosure and the spokesperson could be describing one count. 7,900 is a different kind of record again. BleepingComputer writes that the threat actor "retrieved 32 files from each customer". That is not what the advisory says: it says 32 collected files, each corresponding to one customer server. The advisory is the source; the article misreads it.
Stated and not stated
"Not stated" means not found in the pages read in full on 4 November 2026. It does not mean the information does not exist.
What the OPSSHIELD notices state and what they do not. Read 4 Nov 2026.
| Topic | Stated | Not stated |
|---|---|---|
| Who | An attacker; one address labelled the main operator address; a false customer identity | Who the attacker is, where they are, who runs the address |
| The flaw | Crafted requests to callback pages; two possible entry points patched | The vulnerability, its class, or the request; the logs do not hold it |
| How many ran it | About 2,950 ran the fake update; update checks run at intervals so some may not have | A count of servers that did run it, or the install count by version |
| How much was retrieved | 32 files confirmed, preliminary | What the 32 imply for the other servers |
| Use of what was taken | Licence keys being reissued so the attacker's copies stop working | Whether any stolen password, key or token has been used |
| Leftovers | Hidden shell, scheduled task and directories removed by updates | Whether any of them persisted on a customer server after cleanup; absence does not show the script never ran |
| Update signing | The attacker took the keys used to publish updates; the vendor will harden its update and signing process | How cPGuard checks an update before running it as root, or whether it checks a signature |
| Detection | Within 12 hours of the launch (advisory) | When, or how: no time or method in either notice |
| AI use | The vendor writes that the speed reflects attackers' AI tools | Any evidence of AI use by the attacker |
The row on update signing is the quietest and the most important. The disclosure sequence runs from command ability on the billing and licensing server to the update publishing keys being taken. It implies that the keys were reachable from that server. It does not say where they were kept, and neither notice says whether the agent verifies anything about an update it is handed. They are silent, and silence is not a control.
A ranked checklist, strictest reading first
Where OPSSHIELD gives advice, the items follow its words and say which notice. Anything else is labelled as this site's suggestion. None of it needs an attacker's tooling, and none is given here.
Take this with you
What to do, in order
- 1. Work out whether you ran an affected build. OPSSHIELD's check (advisory): search the install log for lines that read Successfully updated; any version from 5.88.12 to 5.88.19 means treat the server as potentially compromised, even if it now runs 5.88.25 or later. The strict reading, this site's suggestion: also treat as exposed any server that had cPGuard online between 02:08 and 03:20 UTC on 2 November, and any server whose log is missing or incomplete, because the advisory says a missing or incomplete log does not show the server was unaffected. Convert log times to UTC first.
- 2. Update to the newest version. OPSSHIELD's commands (advisory) are in the technical details. The advisory says 5.88.25 or later and the disclosure names 5.88.26; the changelog lists both. This site's suggestion: take 5.88.26 or later, the number that satisfies both pages. Then verify the installed version.
- 3. Rotate in the order the data exposes. From the two notices together: reset the root and every local user password from a trusted recovery environment (advisory); generate new root SSH keys and remove the old public keys from every system that trusted them (both notices); treat other servers you reach from this one with SSH keys as exposed until their keys are replaced (disclosure); change the MySQL root password and any database passwords in /root/.my.cnf (disclosure); rotate keys in /root/.s3cfg and S3 access keys (both notices) and DigitalOcean tokens (advisory); rotate every password, key or token that appears in root's shell history (both notices); change passwords reused on other systems (advisory).
- 4. Check for the leftovers, then do not trust an absence. Look for every path in the technical details, from both notices: the hidden shell, the collection directory and archive, the scheduled task and its directory. The disclosure says to confirm they are gone after the update and delete them if not. The advisory says their absence after cleanup does not establish that the script never ran. Check from a trusted environment where you can.
- 5. Decide about a rebuild with both positions in view. The advisory does not recommend one routinely and calls that provisional; the disclosure says to rebuild from a clean backup taken before 1 November if the vendor told you the attacker logged in by hand. This site's suggestion: ask OPSSHIELD in writing whether your servers were among any where a manual login was seen, and rebuild if you cannot establish integrity, which the advisory itself allows.
- 6. If you hold a billing portal account, reset its password and turn on two factor login, as OPSSHIELD asks, even if cPGuard was not online in the window. The disclosure says about 7,900 accounts were copied, with name, company, postal address and email. This site's suggestion: expect messages that use those details, and reach the vendor only by a login page you type yourself.
- 7. If you run hosting, ask your own vendors how an update is signed, who can publish one, where the publishing key lives and what your agent checks before it runs an update as root. Neither OPSSHIELD notice says how cPGuard signs or verifies updates; this is this site's suggestion, not the vendor's advice.
OPSSHIELD also lists what it has done: revoked the stolen update storage key and every cloud API token and access key on its account; removed the attacker's SSH key, cloned servers and snapshots; replaced SSH keys and passwords across its own servers; started reissuing all cPGuard licence keys; reset every billing portal session and rotated billing and reseller API keys; is rebuilding its billing, licensing and internal management servers from clean images with full request logging; closed the attacker's fake account and trial licence; and is fixing temporary bans on nftables firewalls. It offers help at no charge. These are statements, not findings this site could check. The disclosure ends with an apology, "We are sorry."
An update channel is trusted to run as root on the machine it protects
A server security agent runs as root because it has to read everything. Its update channel inherits that authority: whoever can publish to the channel can run code as root on every server that polls it. OPSSHIELD's two notices describe that inheritance being used once. They do not describe a control that would have stopped it, and the disclosure says the vendor will now harden its update and signing process.
The same shape has been seen on this site before. In the Rank Math PRO incident the only test for a site owner was a download window, not a version number. In the AOMEI Backupper update case a checksum served with the file could not verify the server. Here the version range, the 70 minute window and the log lines are three tests, and the vendor's pages do not yet line them up.
Technical details
Everything below is copied from OPSSHIELD's two notices as printed on 4 November 2026, except that the one live attacker address is defanged. The pages print no script contents and no commands the attacker ran, and this briefing reproduces none. A defender uses these to hunt, and to check that cleanup actually removed what the vendor says it removes.
The vendor's own check for an affected install, and the example lines it prints. Run the search on the server's install log; any version from 5.88.12 to 5.88.19 counts. The advisory says its example timestamps may differ from yours.
grep 'Successfully updated' /opt/cpguard/logs/install_log
[02-11-2026 02:46:04]: Successfully updated to 5.88.12
[02-11-2026 04:46:01]: Successfully updated to 5.88.15
[02-11-2026 08:46:02]: Successfully updated to 5.88.17
[02-11-2026 10:46:01]: Successfully updated to 5.88.18
[02-11-2026 12:46:01]: Successfully updated to 5.88.19
The vendor's update and version commands. The advisory says the installed version must be 5.88.25 or later; the disclosure names 5.88.26.
cpgcli update --start
cpgcli --version
Indicators on a customer server, advisory first. Each is a path the vendor says the fake update created or the corrective update removed. The advisory adds that their absence after cleanup does not establish whether the script previously ran.
Malicious script filename
cpguard-v58812-i91511.sh
Backdoor shell removed by the corrective update
/var/tmp/.cpg91511_sh
Collection directory removed by the corrective update
/var/tmp/.cpg91511
Archive staged by the script
/var/tmp/.cpg91511/loot.tgz
The disclosure's indicator rows for the attack, as the vendor prints them: probe files and web shells in "the web root" (the page does not say whose), the URL pattern of the endpoints that received stolen data, the scheduled task and directory the advisory does not list, the hidden root shell and the script names. The vendor says its own file names follow an i9xxxx pattern.
Type: File
Indicator: /i90248_probe.txt, /i90573_probe.txt, /i90573_sh.php, /i90573_x.php in the web root
Notes: Probe files and web shells; the attacker's file names follow an i9xxxx pattern
Type: URL path
Indicator: *_rx.php
Notes: Endpoints the attacker used to receive stolen data
Type: File
Indicator: /etc/cron.d/i93677, /var/tmp/.i93677/
Notes: Scheduled task left by the fake update
Type: File
Indicator: /var/tmp/.cpg91511_sh
Notes: Setuid-root shell left by the fake update
Type: File
Indicator: cpguard-v58812-i91511*.sh
Notes: Fake update scripts (four variants)
The four hashes the disclosure prints for the four script variants, in full.
SHA-256 2c2acd988da531d133d0e17f245c49bf15781278f837543d18c95e8410eabd38 cpguard-v58812-i91511.sh
SHA-256 ffd7a47f65fa1244429baa936ae94be54676b53d2f88bc39564f24e22011de8a cpguard-v58812-i91511b.sh
SHA-256 d73919af84bf46de941db85e27fd1abc65701ef9ce6cf33bb27c5397f4a41c26 cpguard-v58812-i91511c.sh
SHA-256 6add0201e9a3d02de772d561d05e0da86eb1c538686753b7adcc3aedf7366f77 cpguard-v58812-i91511d.sh
The attacker address the vendor prints, defanged here with square brackets. The vendor labels it the main operator address and says it sometimes sent a fake cPGuard user agent with version 5.88.11, the last build the changelog lists before the affected range. This briefing makes no claim about where the address is or who runs it.
Type: IP
Indicator: 94[.]183[.]188[.]91
Notes: Main attacker operator address; sometimes sent a fake cPGuard/5.88.11 user agent
Three rows the disclosure says come from OPSSHIELD's own internal server, not from customer servers. They are listed so other hosting teams know what the vendor found on its own side. The vendor adds that the implant hides itself from standard tools, so it advises checking from a trusted boot environment or a known good static binary.
Type: File
Indicator: /usr/bin/defunct, defunct.service, /lib/systemd/system/defunct.dat
Notes: gsocket backdoor; process shown as [slub_flushwq]
Type: File
Indicator: /usr/sbin/pythno3, /usr/sbin/netstat.cfg, /etc/profile.d/bash.cfg, /usr/lib/system.mark, /usr/lib/libgdi.so.0.8.2, /boot/system.pub
Notes: Go implant copies; process shown as [rcu_gp]
Type: File
Indicator: /etc/profile.d/gateway.sh
Notes: Hides the implant from ps, netstat, ls and find
The cPGuard changelog entries for the two security patches, as printed on the vendor's public changelog on 4 November 2026.
v5.88.26
Security Patch
November 2, 2026
Improvements
Revoked support access to servers if it is enabled
please read the security advisory for details.
v5.88.25
Security Patch
November 2, 2026
Improvements
Patched compromised update...
Please read the security advisory for details.
The question the two notices leave
A fake update live for about 70 minutes and a set of affected builds whose own example log lines span ten hours do not obviously describe the same exposure, yet the vendor's two notices, both dated 3 November, set them side by side. If the agent on your server runs as root and installs whatever the vendor's channel serves, which line in your own logs would tell you whether the bad update lasted 70 minutes or ten hours, and who would have the keys to find out?
Key facts
Sources
- PrimarySecurity Incident Disclosure: manage.opsshield.com, 3 November 2026: timeline in UTC, what the fake update read, counts, actions, indicators and the apology. Read in fullOPSSHIELDaccessed 2026-11-04
- PrimarycPGuard security advisory: Update channel compromise, published 3 November 2026, last updated 3:19 AM IST: affected versions, update history check, data collected, rebuild question, indicators, two dated sub updates. Read in fullOPSSHIELDaccessed 2026-11-04
- PrimarycPGuard changelog, read for the entries on 5.88.25 and 5.88.26 dated 2 November 2026 and for what it does not listOPSSHIELDaccessed 2026-11-04
- PrimaryVendor blog index, read to check for a further incident post; none listed on 4 November 2026OPSSHIELDaccessed 2026-11-04
- Reported byNews article of 3 November 2026 (22:18 UTC) quoting the advisory and a company spokesperson's figure of 2,946 servers; secondary, used only for that figure and for the press framingBleepingComputeraccessed 2026-11-04


