The key nobody rotated: Zeabur, PingCAP and k0t
Zeabur, PingCAP and k0t, read from the primary reports: why the age and reach of a secret decided each breach, with seven charts and a four-hour audit to find yours.
Cybersecurity21 min read
Contents
- The short version
- Zeabur: the token that outlived the rotation
- August: the first breach
- What the rotation missed
- 14 and 15 October
- What Zeabur says it got wrong
- What is still unknown
- PingCAP: 28 days on a service account
- What was taken
- Reported against claimed
- k0t: the edge appliance that kept the keys
- How k0t gets in
- The default key
- Scale, links and what is not confirmed
- LiteLLM, five months on
- What the three share: age, scope and visibility
- Age
- Scope
- Visibility
- What I cannot say
- A four-hour audit for the oldest key you own
- Hour 1: cloud identities and tokens
- Hour 2: where copies hide
- Hour 3: defaults that never changed
- Hour 4: alerts on valid access
- If you were a customer
- Sources
Contents
- The short version
- Zeabur: the token that outlived the rotation
- August: the first breach
- What the rotation missed
- 14 and 15 October
- What Zeabur says it got wrong
- What is still unknown
- PingCAP: 28 days on a service account
- What was taken
- Reported against claimed
- k0t: the edge appliance that kept the keys
- How k0t gets in
- The default key
- Scale, links and what is not confirmed
- LiteLLM, five months on
- What the three share: age, scope and visibility
- Age
- Scope
- Visibility
- What I cannot say
- A four-hour audit for the oldest key you own
- Hour 1: cloud identities and tokens
- Hour 2: where copies hide
- Hour 3: defaults that never changed
- Hour 4: alerts on valid access
- If you were a customer
- Sources
Zeabur's admin token was created on 10 January 2024 and had no expiry. On 14 October 2026 an attacker used it to take over the company's shared clusters, and Zeabur says everything will be switched off by 31 December.1, 3
That token is the clearest example I found of something that showed up in three separate disclosures in the week of 19 October. PingCAP, which runs TiDB Cloud, said an intruder used stolen service-account credentials for 28 days.4, 6 Group-IB and NyxLab described an operation, tracked as k0t, that decrypted stored passwords from firewall configuration files using a key Fortinet has shipped since 2019.7 In each case the credential that did the damage was old, broad, or both, and the organisation's own rotation had not touched it.
Day zero was about keys taken from places that got breached. This post is about the other side, where the key was already sitting there. I read each company's primary report first, then the coverage around it, and the labels below say which is which.
The research is current to 26 October 2026. Zeabur's report is preliminary and PingCAP is still working out which customers are affected, so check the sources before you act on any figure here.
- Reported. Stated in a primary report from the company, its forensic firm or the researchers, with the source cited. A company describing its own breach is still giving its own account.
- Claimed. Said by one party, usually an extortion group, and not confirmed by anyone else.
- My analysis. My reading. The comparisons in the middle of the post and the four-hour audit are mine, and the figures that draw on them say so.
The short version
All three incidents turned on a secret that stayed valid long after it should have stopped working. None of them needed a new vulnerability, and I found no source that links the three to one actor.
| Incident | The credential that mattered | How long it was useful | How the defender found out |
|---|---|---|---|
| Zeabur | Shared-cluster admin token with no expiry, in plaintext in a config repository | About 2 years 9 months old when used | A user report, 36 h 20 min after the first stolen key was used1 |
| PingCAP | Service-account keys in git history and plaintext Terraform state, plus customer AWS keys pasted into Jira | Access ran 9 Sep to 7 Oct, 28 days | PingCAP says it became aware on 7 Oct and does not say how4, 5 |
| k0t | Secrets inside downloaded firewall configs, encrypted with Fortinet's default key | The key has been the same since 2019 | Not visible on the device, because decryption happens offline7, 10 |
The practical question these raise is small. Which of your secrets is the oldest one that still works, and what can it reach? I finish with a four-hour audit for that. Before it come the three incidents in detail, a correction to Day zero on LiteLLM, and the comparison.
Zeabur: the token that outlived the rotation
Zeabur's own report says the root cause was a shared-cluster admin token created on 10 January 2024, with no expiry, that sat in plaintext in a private configuration repository and was left out of the rotation that followed the company's August breach.1
August: the first breach
Reported. On 27 August an attacker used CVE-2026-7644, an authorization bug in the MCP feature of NextChat v2.16.1, to run code inside a customer's service on a shared Zeabur cluster. The earliest request Zeabur can tie to the attacker is at 02:34 UTC. Two minutes later they used a team administrator's Legacy API Key, which they had read from the platform's routing cache. Those keys had no scopes and no expiry.2
Reported. At 05:39 the attacker read the environment variables of an internal management service and found a long-lived AWS root user key. They authenticated to Zeabur's AWS account as root at 05:45. At 07:26 a service account was given cluster-administrator rights, and from 11:52 they were bulk-reading production environment variables, using a database credential held by a maintenance job on the shared cluster.2 Zeabur got its first report of API key abuse at 02:34 on 28 August and sent its first notice to users that morning.2
On 7 September Zeabur published its account and said it had "disabled or rotated every internal administrative key, database password, and cache password".2 That sentence covers every key Zeabur knew about. The rest of this section is about the ones it did not.
What the rotation missed
Reported. During the August intrusion the attacker had read Zeabur's GitHub App private key. Zeabur replaced that key on 31 August. The private configuration repository it protected still held plaintext AWS keys and the cluster admin tokens, and the repository had been downloaded as an archive on 30 August and again on 2 September, through an employee's GitHub authorization. Zeabur does not know who downloaded it.1
Reported. The admin tokens had been created on 10 January 2024 with no expiry, and written into the repository in plaintext on 20 January 2026. They were about 2 years 9 months old when the attacker used them.1
Reported. Two other problems were known and still open. On 3 September Zeabur found that root passwords for its GCP dedicated servers were being written in plaintext into server initialization settings. Between 1 and 5 September an unknown source signed in as root to about 98 of those servers, and Zeabur cannot say whether that is connected to October. Neither was fixed by 14 October, and a secrets migration Zeabur started on 3 October had not been merged.1
14 and 15 October
Reported. The attacker's IP shows up in Zeabur's API logs from 10 October, and three dedicated servers saw failed SSH attempts on the evening of 13 October. The intrusion itself began at 01:36 UTC on 14 October with a Zeabur AWS key. Four minutes later the attacker presented a cluster admin token to the shared-cluster admin interface, which was reachable from the public internet.1
Reported. By 12:39 they had read the settings and secrets of every service on the shared cluster, across nine regions. From 13:40 to 17:04 they ran commands inside 865 database services. In parallel they used an old GCP service-account key to read the server initialization settings, took the root passwords from them, and signed in as root to 101 dedicated servers. BleepingComputer counts those across 92 users.1, 3 They put their own SSH keys on 50 of the servers, created five VMs in Zeabur's GCP project and attached copies of 16 customers' disks to them.1
Reported. Zeabur began investigating at 13:56 UTC on 15 October, after a user report. That is 36 hours 20 minutes after the first stolen key was used, a figure I worked out from Zeabur's timeline. Zeabur says more than 16 hours of attacker activity on 14 October raised no alert, because every request used a valid credential through an access path Zeabur allowed.1
Zeabur, hour by hour
- Attacker activity
- Zeabur's response
Data table: Zeabur timeline events
| Event | Who | Hours since 01:36 UTC, 14 Oct |
|---|---|---|
| First use of a Zeabur AWS key | Attacker | 0 |
| Admin token used on the shared cluster | Attacker | 0.1 |
| Secrets of every shared-cluster service read | Attacker | 11.1 |
| Database containers and GCP root sign-ins begin | Attacker | 12.1 |
| Last command inside a database container | Attacker | 15.5 |
| Deploy key of a retired service reads the config repo | Attacker | 37.4 |
| Rogue node joins the internal network | Attacker | 37.9 |
| Customer database backup downloaded | Attacker | 38.1 |
| Platform database read begins | Attacker | 38.6 |
| API calls as two impersonated users | Attacker | 38.6 |
| Backup key captured after rotation is reused | Attacker | 42.9 |
| Last attacker activity seen | Attacker | 43.5 |
| Investigation starts after a user report | Zeabur | 36.3 |
| Admin interface restricted | Zeabur | 37.1 |
| Rogue network node removed | Zeabur | 40.4 |
| Login signing key rotated, all users signed out | Zeabur | 42.8 |
| Public SSH to GCP servers blocked | Zeabur | 43 |
The seven hours after Zeabur started looking show how many credentials it had not inventoried, because it kept finding more. It restricted the admin interface at 14:43. Between 14:52 and 16:51 the attacker read about 53 production secrets from the secrets service. At 15:02 a deploy key for a decommissioned service read the configuration repository. It had stayed valid for four months after the service was retired, and Zeabur thinks the attacker used it but has no direct record. At 15:05 the GitHub App private key was read again.1
Reported. At 15:30 the attacker used a compromised GCP server and internal credentials to add a node to Zeabur's internal network. From that node, between 16:10 and 16:47, they read the platform database through an internal read-only account that could read everything in it. They also forged login credentials with a signing key taken earlier and called Zeabur's API as two users, one of them an employee. Zeabur rotated the signing key at 20:25 and signed everyone out. At 20:30 the attacker used a backup access key that had been captured in a backup taken after Zeabur rotated it. Public SSH to the GCP servers was blocked at 20:36, and the last attacker activity Zeabur saw was at 21:05.1
Reported. From the platform database the attacker took 3,218,965 environment-variable records, profile data (including email and phone) for 321,810 accounts, 566 zSend API keys stored in plaintext, and 11,536 access tokens, which were hashed. One customer database backup was downloaded through a presigned URL. On 16 October, between 01:50 and 02:56 UTC, a user's OpenAI key was abused. Zeabur thinks that is linked and says it cannot prove it.1
What the attacker reached at Zeabur
Data table: Zeabur blast radius
| What | Count |
|---|---|
| Environment-variable records | 3,218,965 |
| Account profiles | 321,810 |
| Access tokens (hashed) | 11,536 |
| Database services reached | 865 |
| zSend API keys (plaintext) | 566 |
| GCP servers, root sign-ins | 101 |
What Zeabur says it got wrong
Zeabur's report lists its own failures plainly, and that list is why this section can be specific. It says:
- Admin credentials were long-lived, stored in plaintext and usable from the public internet.
- The August rotation did not cover them, and the claim in the 7 September report was incomplete. Zeabur is correcting it.
- Cluster backups held every secret, and the backup key sat next to the other secrets.
- An AWS key meant for one bucket could read all of them, the GCP default service account had project-level write, and an internal read-only database account could read all data.
- The shared cluster and the user services shared an environment, so reading a user's settings exposed internal credentials.
What is still unknown
Zeabur does not know how the attacker got the plaintext tokens. Its working theory is the GitHub App key read in August, and it calls that unproven, with an employee-authorized download as the other possibility. It also cannot say whether the 1 to 5 September root sign-ins are linked, whether its Hetzner (359 servers) and DigitalOcean (48 servers) accounts were reached, or whether the Taipei and Hong Kong user database backups were downloaded.1
The founder announced the shutdown over the weekend of 17 October.3, 13 Renewals stop on 1 December and every shared cluster and dedicated server is off by 31 December. The reasons given were the limits of Zeabur's capacity for AI deployments, the complexity of the system and the two incidents.3
PingCAP: 28 days on a service account
PingCAP's report says an unauthorized party used stolen service-account credentials from 9 September to 7 October 2026. It gives no detail on how. NebuSec, the forensic firm PingCAP brought in, gives a good deal.4, 6
Reported, NebuSec. The attacker came in through a compromised GitHub account that could read private repositories. NebuSec does not say how the account was compromised. In those repositories it found service-account private keys sitting in git commit history, plaintext Terraform state files, and a plaintext Jira API token and a bot key. Together they opened Google Cloud, Jira and the internal chat system used for TiDB alerts.6
Reported, NebuSec. Jira gave the attacker one more thing. Customers had pasted AWS keys into support tickets while asking for help, and the attacker harvested those and used them against S3 buckets holding TiDB diagnostic data.6
Reported, NebuSec. The copying was organised. Bulk BigQuery export jobs wrote 6,458 tables as compressed JSON to Cloud Storage on 23 and 24 September, and downloads ran through rclone on 2 and 3 October. PingCAP became aware on 7 October and began disabling credentials the same day. By 14 October it had invalidated every credential it identified and blocked every access path it found.4, 6
PingCAP, 9 September to 23 October
- Attacker activity
- PingCAP's containment
- Public reports
Data table: PingCAP timeline
| Phase | When |
|---|---|
| Attacker in the systems | 9 Sep to 7 Oct, 28 days |
| Bulk BigQuery exports | 23 to 24 Sep, 6,458 tables |
| rclone downloads | 2 to 3 Oct |
| Containment | 7 to 14 Oct |
| Public reports | 19 and 23 Oct |
What was taken
Reported, NebuSec. The list is long. It covers copies of control-plane metadata, customer SQL editor history, AI interactions and gateway connection logs, CRM, contract, order, billing and cloud cost records, usage analytics, employee and department information, support tickets with their attachments (including logs and SQL files with credentials in them), source code, Jira issues, chat history and group membership, and infrastructure configuration and orchestration backups.6
Reported. PingCAP and NebuSec say there is no evidence that data stored in customers' TiDB clusters was touched. The forensic firm saw no command execution or persistence in the production systems it reviewed. A source review also turned up four vulnerabilities, which were fixed and retested by 14 October, and PingCAP is checking production logs for any sign they were exploited.4, 5, 6
Reported against claimed
The extortion group FulcrumSec listed PingCAP on its leak site on 19 or 20 October. Its numbers are far bigger than anything PingCAP has confirmed, and a few of them contradict NebuSec directly.8 Here are both sides, row by row.
| Topic | Reported (PingCAP, NebuSec) | Claimed (FulcrumSec) |
|---|---|---|
| Console API keys | Exported values were encrypted and the key was not exposed. NebuSec tested one and could not use it as a key.6 | 115,308 key pairs stored in plaintext, 42,612 of them active |
| SQL editor data | Exported records include SQL editor text and errors6 | 20.6 million raw SQL statements |
| Volume | Categories listed, no total given | 10.6 TB, about 4.9 million files |
| Customers affected | Still being worked out, and PingCAP will contact them directly4, 5 | 180,046 organisations |
| Source code | Obtained4, 6 | 413 repositories |
| Live customer clusters | No evidence customer data in TiDB was affected4, 6 | Not claimed, according to the analysis I read8 |
My analysis. The first row is where I would not take either side yet. "Encrypted in this table" and "unusable by the attacker" are different conditions. An encrypted value stays safe only while the key stays out of reach, and for 28 days the attacker had source code, Terraform state and cloud configuration to read. NebuSec says its finding does not cover credentials shared in support materials, and those were in the data.5, 6 I also cannot tell from the public reports what the 115,308 figure counts. It could be plaintext keys or it could be rows that are encrypted, and FulcrumSec has published no sample I could check.
The SQL editor row matters more than it looks. People paste connection strings and tokens into query boxes. If you used TiDB Cloud's SQL editor, search your own history before you assume it is clean.
Not stated. PingCAP does not say how it detected the intrusion, how the GitHub account was compromised or which customers are affected.4, 5, 6
k0t: the edge appliance that kept the keys
Group-IB and NyxLab's report of 21 October describes more than 70,000 credentials and related records collected from FortiGate, FortiWeb and Palo Alto GlobalProtect devices that face the internet. The collection ran on a few bugs, some weak admin logins and one key that never changes.7
How k0t gets in
Reported. The actor, k0t, works with likely aliases or collaborators called CryptoFeel and Scrooge. It uses FOFA, ZoomEye and Censys to export lists of exposed devices in ip:port form and goes after whatever is on them. Targeting is opportunistic. The stated priority is the US and Canada, then Europe, then selected APAC markets.7 There are three routes in.
- On FortiWeb it uses CVE-2025-64446, a path traversal. A crafted request with a forged header that impersonates the built-in
prof_adminaccount creates a local admin with a random eight-character name and password and a trusted-host range of 0.0.0.0/0. - On GlobalProtect it uses CVE-2026-0257, an authentication bypass that only works where authentication-override cookies and a particular certificate setup are enabled. The attacker forges a cookie encrypted with the target's TLS certificate public key, submits it with an empty password to
/ssl-vpn/login.esp, and connects with OpenConnect. - FortiGate is not vulnerable to the FortiWeb bug, so k0t brute-forces its REST API with a short built-in list (admin, fortinet, fgtsecure) plus an operator wordlist. When a device locks the account out, the tool waits 60 seconds, which matches the default admin lockout.7
How k0t turns a firewall into a domain
Step 1
Find it
Lists of exposed devices from FOFA, ZoomEye and Censys.
Step 2
Get in
A patched-late bug on FortiWeb or GlobalProtect, or brute force on FortiGate.
Step 3
Download the config
A copy of the appliance configuration, with secrets stored as ENC strings.
Step 4
Decrypt offline
The default FortiOS AES key opens every ENC string. The device sees nothing.
Step 5
Use the bind account
LDAP and Active Directory credentials recovered from the config.
Step 6
Reach the domain
noPac in some intrusions, then Domain Admin, with rclone and remote-management tools after.
Where the fix sits: step 4. Enabling private-data-encryption with your own key makes the downloaded config undecryptable with the default one.
Data table: k0t's path
| Step | What happens |
|---|---|
| 1. Find it | Lists of exposed devices from FOFA, ZoomEye and Censys. |
| 2. Get in | A patched-late bug on FortiWeb or GlobalProtect, or brute force on FortiGate. |
| 3. Download the config | A copy of the appliance configuration, with secrets stored as ENC strings. |
| 4. Decrypt offline | The default FortiOS AES key opens every ENC string. The device sees nothing. |
| 5. Use the bind account | LDAP and Active Directory credentials recovered from the config. |
| 6. Reach the domain | noPac in some intrusions, then Domain Admin, with rclone and remote-management tools after. |
The default key
Reported. The step that belongs in this post comes after the login. Run with its --parse-configs option, k0t's tool downloads the FortiGate configuration and decrypts the stored secrets on the operator's own machine, using the default FortiOS AES key. That recovers LDAP and Active Directory bind credentials, admin and local-user credentials and more. Group-IB points out that this happens offline, so the appliance cannot detect it. From there the operators used noPac (CVE-2021-42278 and CVE-2021-42287) to reach Domain Admin in some intrusions.7
The default key is the subject of CVE-2019-6693. Fortinet published advisory FG-IR-19-007 in November 2019 and updated it in June 2020. FortiOS, FortiManager and FortiAnalyzer used a fixed symmetric key, built into the software, to encrypt every ENC-type secret in CLI configuration files and unencrypted backups, apart from the primary administrator's password hash. Fixed versions are FortiOS 5.6.11, 6.0.7 and 6.2.1.10
Reported. The fix is a setting, and the upgrade does not apply it. An administrator has to enter config system global, run set private-data-encryption enable and supply their own 32-digit hexadecimal key. Fortinet says the setting is off by default. It also warned that turning it on for units managed by FortiManager, or running in HA clusters, caused install errors and HA split-brain until FortiManager 6.2.7 and FortiOS 6.2.6, 6.4.4 and 6.6.0.10 Group-IB's advice is to enable it, treat any exposed config as a credential disclosure, and rotate everything stored in it, LDAP and AD bind accounts included.7
My analysis. That history is a plausible reason many teams left it alone. A firewall upgraded every year since 2019 can still be protecting a freshly rotated LDAP password with a key from 2019. No source I found counts how many devices are in that state, so I will not guess.
Scale, links and what is not confirmed
Reported. Group-IB found 28 active device groups with 84 compromised devices beaconing to the operators' MeshCentral server, and says another 100 groups were removed. APAC accounts for 37.6% of the unique domains it identified, and it treats that count as a lower bound. Many FortiGate compromises date from February to June 2026. For persistence and exfiltration the operators used OpenConnect, MeshCentral, AdaptixC2, Atera, AnyDesk and ngrok, and rclone to Wasabi and MEGA. Group-IB also found an AI pentesting tool among the operator's tooling and reports no evidence it was used.7
Reported. Victims overlap with organisations later listed by the Qilin and The Gentlemen ransomware groups. Group-IB says it has not confirmed that k0t is affiliated with either, and it assesses that k0t may be an initial access broker. It links the activity to the FortiBleed cluster from June with moderate confidence, but the credential data from the two overlaps negligibly, and Group-IB says that does not show the same operators held both.7 A claim in secondary coverage that k0t sold access to Inc ransomware is not in the Group-IB report, so I left it out.
LiteLLM, five months on
My own Day zero piece needs a correction on LiteLLM, and it fits this post because the corrected cause is also a key nobody revoked.
In Day zero I wrote that LiteLLM's own theory was that GitHub CLI tokens had leaked into the logs of an internal deployment.12 LiteLLM's 23 October root-cause analysis changes that. I could only read it through TokenPost's summary, so treat the details as secondhand. A config file holding the master key for a LiteLLM Agent Platform deployment was committed to a public repository, LiteLLM-Labs/lite-harness, on 27 May. The commit was later force-pushed over and some exposed keys were flagged for revocation, but the master key was not revoked.9
Reported. On 10 October the attacker used that key against the platform's API. One response returned the configuration of every managed agent, including a GitHub CLI OAuth token for one of the two GitHub organization owners. LiteLLM says the token was not tied to a service account and had not been scoped down. Two more maintainer tokens came from CI workflows that posted repository secrets to webhook.site. On 21 October the owner's token overrode branch protections and redirected the release workflow from BerriAI/litellm to a lookalike repository, Berri-AI/litellm. The master key was 147 days old on release day.9
Day zero also gave the PyPI exposure as about an hour and forty minutes. That is right for PyPI, but the container images stayed up longer.
LiteLLM, 21 October
- Poisoned release live
- Outline: attacker testing stolen keys
Data table: LiteLLM exposure windows
| Event | When (UTC) |
|---|---|
| PyPI wheels live | 11:39 to 13:20, 1 h 41 min |
| Docker Hub and GHCR images | 11:46 to 14:20, 2 h 34 min |
| Stolen AWS key tested | 16:20 to 17:01 |
Reported. Wiz's ClickPy figure is roughly 49,000 downloads of 1.107.0 from PyPI. Wiz saw stolen AWS credentials being tested between 16:20 and 17:01 UTC, about 4.5 hours after the release went live.11 The safe version is 1.106.2.
What the three share: age, scope and visibility
Three things repeat across the incidents, and the one I would check first is age. This section is my own comparison. It rests on three vendor accounts and one threat report, and it does not measure how common any of this is.
Age
How old the key was
Data table: Key age
| Key | Months valid |
|---|---|
| Fortinet default key, since 2019 | 83 |
| Zeabur cluster admin token | 33 |
| LiteLLM leaked master key | 4.8 |
My analysis. Zeabur's token was 33 months old. LiteLLM's master key was under five months old, which is still well past a 90-day rotation. The Fortinet default has been the same for 83 months, though that counts the age of the default, not any one customer's key. PingCAP gives no ages, but service-account keys in git commit history are long-lived by nature, because deleting a file from a repository does not delete the key from the history, and Terraform state files keep whatever the last apply wrote into them.
Rotation also has a second way to fail, and Zeabur shows both. The August rotation ran against the keys the team knew about. The repository with the plaintext tokens was not on that list. Then, on the day of the attack, a backup taken after the backup key was rotated captured the new key, and the attacker used it five hours later.1 A rotation that does not ask where else a secret is stored has not finished.
Scope
Reported. Zeabur says an AWS key meant for one bucket could read all of them, an internal read-only database account could read all data, and the GCP default service account had project-level write.1 PingCAP's service accounts had cross-project permissions, and NebuSec describes the attacker moving from repositories to Jira, chat and cloud storage.6 In k0t's chain, the bind account stored on a firewall led to domain-wide enumeration in intrusions that went on to Domain Admin.7 LiteLLM's owner token was not scoped down.9 None of these keys needed to do as much as it could.
Visibility
How long before the defender acted
Data table: Time before the defender acted
| Incident and clock | Time |
|---|---|
| PingCAP: access window before it noticed | 28 days |
| Zeabur: first key use to investigation | 36 h 20 min |
| LiteLLM: poisoned PyPI release, live | 1 h 41 min |
My analysis. A stolen credential that still works looks like ordinary work. Zeabur's 16 hours of attacker activity and PingCAP's 28 days both ran on valid keys. In k0t's case there is nothing for the defender to see at all, since decryption happens on the attacker's own machine. LiteLLM is the fast one on the chart, but the 1 h 41 min shows how long the bad release was up on PyPI, and the attacker had started testing keys within about four and a half hours of it going live.
What I cannot say
Zeabur's report is preliminary and its logs for storage, GCP and GitHub access are incomplete, so its scope may change. PingCAP gives few details of its own and leans on NebuSec. I read Group-IB's report directly, but its counts are lower bounds, and I could not check Fortinet's advisory details against a second source. For LiteLLM I only had a summary of the root-cause analysis. I also cannot tell you how common unrotated keys are. Three incidents in one week show they exist, and nothing more.
A four-hour audit for the oldest key you own
You can find your own Zeabur-shaped token in an afternoon by ranking secrets by age and reach, not by rotating from a list. Work through the stores in this order.
Hour 1: cloud identities and tokens
Export every access key, service-account key and cluster token, and sort by creation date. Anything with no expiry, or older than 90 days with wide reach, goes to the top. Give every service account one human owner and one purpose, and remove any cross-project binding or wildcard bucket read. Delete a retired service's deploy keys and cloud roles on the day it goes, because Zeabur's stayed valid for four months.
# AWS: a credential report with key ages
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 -d
# GCP: user-managed keys for one service account
gcloud iam service-accounts keys list --iam-account=SA_EMAIL --managed-by=user
Hour 2: where copies hide
Scan the full git history of your configuration and infrastructure repositories, not only application code. Look at remote Terraform state, VM initialization metadata, support tickets and chat. Check that no backup contains the key that protects the backup. If customers paste keys into your tickets, as PingCAP's did, set up a way to redact them and ask people to rotate after support.
# every verified secret in the repo's history, not just the working tree
trufflehog git file://. --only-verified
Hour 3: defaults that never changed
On every FortiGate, check whether private-data-encryption is on. If it was ever off, treat each old configuration backup as readable, and rotate the LDAP and AD bind account, VPN secrets and admin credentials stored in the config. Keep management interfaces off the public internet and require MFA on VPN. Fortinet's own warning applies if you use HA or FortiManager, so test the change first and verify key sync after.
show full-configuration system global | grep private-data-encryption
exec private-encryption-key verify
Hour 4: alerts on valid access
The detection gap is where Zeabur lost 36 hours. Alert on bulk reads from your secrets store, new nodes joining an internal network, disk snapshots attached to unfamiliar VMs, and cloud keys used from networks you do not recognise. Zeabur and PingCAP both say they are adding alerts of this kind.1, 4
If you were a customer
- Zeabur: revoke each credential you stored at its own provider first, then redeploy. Rebuild any GCP dedicated server. For n8n, replace the encryption key and recreate third-party credentials, and for new-api or one-api revoke the upstream AI keys. On PostgreSQL, check for unknown roles, functions, triggers, jobs and extensions. Zeabur's report has the full list, with indicators of compromise.1
- PingCAP: replace TiDB Cloud management API keys and rotate anything you sent to support, including logs that contain secrets. Be careful with phishing that uses your support history.5
- FortiGate, FortiWeb or GlobalProtect: patch the two CVEs above, enable
private-data-encryption, and hunt for unexpected local admins, trusted-host changes, rclone and remote-management installs.7
Zeabur's token was created on 10 January 2024 and was still valid on 14 October 2026. If you cannot say which key you own is the oldest one that still works, that is the first thing to find out.
Sources
- Zeabur. October 2026 security incident (preliminary report). 19 October 2026. zeabur.com
- Zeabur. August 2026 security incident. zeabur.com
- BleepingComputer. Zeabur shutting down after second security breach in two months. 20 October 2026. bleepingcomputer.com
- PingCAP. Security update. 19 October 2026. pingcap.com
- PingCAP. A note from our CEO on the PingCAP security incident. 23 October 2026. pingcap.com
- NebuSec. Investigating the PingCAP security incident: credential exposure and cloud data collection. nebusec.ai
- Group-IB and NyxLab. Stray cat, open doors: how k0t wanders through the network edge. 21 October 2026. group-ib.com
- aiidelist. PingCAP data breach 2026: what FulcrumSec claims and what TiDB Cloud confirmed. Secondary source for the extortion group's claims. aiidelist.com
- TokenPost. LiteLLM traces malicious release to master key left unrevoked. Secondary summary of LiteLLM's 23 October root-cause analysis. tokenpost.com
- Fortinet PSIRT. FG-IR-19-007, hard-coded key in FortiOS (CVE-2019-6693). fortiguard.com
- Wiz. LiteLLM compromised, steals credentials. wiz.io
- The Hacker News. LiteLLM suspects GitHub token leak in AI gateway logs. thehackernews.com
- Zeabur. Zeabur is shutting down. zeabur.com
Topics: Zeabur breach, Zeabur shutdown, PingCAP TiDB Cloud breach, k0t FortiGate, CVE-2019-6693, FortiGate private-data-encryption, credential rotation, secret rotation audit, stale credentials, incident response