An attacker used leaked internal credentials to break into the shared cluster and GCP Dedicated Servers, and then read the environment variables stored in the Zeabur platform database. This post covers what happened, which data was affected, how we responded, and what you need to do.
This article is also available in 繁體中文, 简体中文, 日本語, Español, and Bahasa Indonesia.
All times in this post are in Coordinated Universal Time (UTC).
On October 15, 2026, at 13:56, a user report led us to start an investigation. When we went back through the logs, we found that the attacker had started using Zeabur's internal credentials on October 14 at 01:36, about 36 hours before we noticed. Throughout that time, the attacker used valid credentials over Zeabur's official access channels, and no alert fired.
The attacker came in through two paths that met inside Zeabur's internal network on October 15, and from there read the platform database. None of the credentials used this time were covered by the rotation after the August incident.
| Item | Details |
|---|---|
| Status | Final |
| What you need to do | Replace every password and key stored on Zeabur, including those you replaced after the August incident. See What you need to do |
| Incident window | October 14, 01:36 to October 15, 21:05 (the attacker's last activity in the logs) |
| Detected | October 15, 13:56, from a user report, about 36 hours after the attacker first used the credentials. See Detection |
| Contained | October 15: attacker's internal network node removed at 17:58, public SSH to GCP Dedicated Servers blocked at 20:36, all users signed out |
| Impact | Environment variables and account data in the platform database, services and databases on the shared cluster, and 101 GCP Dedicated Servers. Environment variables that had been moved to users' own servers after August were outside the scope of the read. See What information was involved |
| Most likely cause | Zeabur's private configuration repository leaked; how it leaked cannot be confirmed. The repository held long-lived credentials in plaintext, and the cluster admin interface was open to the public internet. See Root causes |
| Term | Meaning |
|---|---|
| Confirmed | A log records it directly |
| Assessed | The timing and content match, but there is no direct record |
| Cannot be confirmed | There are no records to check, and we treat it as leaked |
| Hypothesis | A possible explanation backed only by indirect evidence, collected in Unconfirmed hypotheses |
Do this now, without waiting for a notification email. Leaked data can still be misused, and credentials you replaced after the August incident need to be replaced again.
Treat your server as compromised:
/root/.ssh/authorized_keys with the comment @zeabur-pentest, and any keys you don't recognize.google-sudoers group, system accounts, crontab, systemd services, and k3s workloads.In the provider's console, check whether the root password was reset or the system was reinstalled after October 14. Then go through the GCP checks above to make sure there is no sign-in method you don't recognize.
| System | Affected data | Scope | Certainty |
|---|---|---|---|
| Platform database | Service environment variables stored on Zeabur (names and values) | 3,218,965 records | Confirmed |
| Platform database | Accounts (email, username, phone number, and so on), project, environment, and service data | 321,810 accounts | Confirmed |
| Platform database | zSend API keys (plaintext) | 566 keys, revoked | Confirmed |
| Platform database | Platform Access Tokens | 11,536 tokens, stored only as hashes that cannot be reversed; all revoked | Confirmed |
| Shared cluster | Environment variables and secrets of all services | 9 regions | Partly confirmed; the rest cannot be confirmed |
| Shared cluster | Database contents | 865 database services | Assessed (see below) |
| GCP Dedicated Servers | All data on the servers | 101 servers, 92 users | Confirmed (sign-ins) |
| Hetzner and DigitalOcean Dedicated Servers | Admin access to the servers | 359 and 48 servers | Cannot be confirmed (use) |
| GitHub App | Access to the GitHub repositories users authorized | 10/15 15:05 to 18:54 | Cannot be confirmed (use) |
| User database backups | Backups in the Taipei (tpe1) and Hong Kong (hkg1) regions | Two regions | Cannot be confirmed (download) |
The details for each system follow.
From 16:10 to 16:47 on October 15, the attacker read the data listed in the table above. Account data includes the information on your profile page, such as email, username, and phone number. For the two-factor authentication and passkey tables, the attacker queried only statistics, and there is no record of their contents being read. Platform Access Tokens are stored only as hashes, and we revoked all of them anyway.
The attacker was mainly looking for API keys they could use right away, especially keys for AI services. They searched environment variables and config files for API keys and private keys, read credentials from n8n and new-api/one-api in bulk, and tried to call Amazon Bedrock with Zeabur's AWS keys. We drew this from the commands they ran and what they did afterward. The attacker also read account data, and we treat everything they read as leaked.
After the August incident, Zeabur gave Dedicated Server users guidance and a one-click migration: rotate credentials, delete the environment variables and config files stored on Zeabur, and keep them on your own server instead. For projects that completed the migration, this data exists only on the user's server and was outside the scope of this read. For projects that had not migrated, environment variables were still stored on Zeabur and were read this time. Leaks from a compromised host are a separate matter, and compromised GCP Dedicated Servers still need the steps in What you need to do.
From 16:12 to 17:19 on October 15, the attacker called the Zeabur API as two accounts and read account and project lists. One of the two was a Zeabur employee's account. These requests did not modify any resources.
The attacker read the key used to sign login credentials, and we assess that they forged login credentials with it. Platform Access Tokens are stored only as hashes, and the attacker did not read them in bulk until 16:47, so the tokens cannot explain impersonation that started at 16:12. At 20:25, we rotated the signing key and all users were signed out.
The attacker ran read commands inside the containers of 865 databases. The audit logs record commands but not their output, and some commands failed with errors, so we cannot confirm how much was actually taken from each database. The table below is our judgment based on the commands:
| Target | Count | Data read |
|---|---|---|
| n8n using PostgreSQL | 736 | Third-party credentials, users, projects, variables, and workflows |
| PostgreSQL (read table by table) | 211 | Up to 50,000 rows per table; none in the Taipei (tpe1) region |
| new-api/one-api | 10 | AI service keys, access tokens, and users |
| Redis | 1 | Entries whose names contain words such as token or secret |
| MongoDB, MariaDB | 1 each | Taipei (tpe0) has no command contents; treated as fully leaked |
We checked 607 of the n8n instances using PostgreSQL, and 602 of them had their encryption key in an environment variable. For those, the third-party credentials stored in n8n were effectively exposed in plaintext. These reads happened inside the containers, so rotating database passwords after the August incident gave no protection against them.
Separately, at least 2 PostgreSQL databases in the Tokyo (hnd1) region had a program planted from October 14 at 01:51 that connected back to an outside host. One of them was still connecting back on October 15 at 16:24. Whether the way in was a password leaked in August cannot be confirmed. When we found this, we told the affected users to replace their credentials.
The attacker signed in to 101 servers with root privileges, most recently on October 15 at 20:36. On 50 of them, the attacker added SSH public keys they controlled, so they could sign in again later. They also created 5 virtual machines in Zeabur's GCP project and attached copies of 16 customer server disks to them.
We treat the data on all 101 servers as possibly leaked, and the servers as possibly backdoored. We have emailed the affected users and reset the root passwords of these servers.
The tokens that manage customer servers on Hetzner and DigitalOcean were written in internal code and environment variables, and leaked with the platform database. Anyone holding them could reset passwords, reinstall systems, or copy disks. We revoked all of these tokens on October 16 at 01:09. Neither provider offers an API for operation audit logs, so we cannot confirm whether the tokens were used. We ruled out one thing: the password resets and image creation on Hetzner on October 15 were done by the customers themselves and by scheduled system jobs. We have no comparable result for DigitalOcean.
Of 890 Linode servers, the 847 that have records show no sign-ins by the attacker. There is no record of Tencent Cloud's admin credentials being used.
On October 15 at 15:05, the attacker read the private key of the Zeabur GitHub App. With this key, anyone can access the repositories users have authorized Zeabur to access. We rotated the key at 18:54. Whether the key was used cannot be confirmed: we did not get the GitHub organization's full audit logs, and GitHub Support never replied to our request for them.
The attacker used several of Zeabur's AWS keys. Most requests were denied, but the attacker listed the user database backups in two regions and the contents of source code uploads. Whether they downloaded any of it cannot be confirmed. Every attempt to call Amazon Bedrock failed, and none of them incurred charges.
| Feature | Impact period (UTC) | Status |
|---|---|---|
| Sign-in | Sign-in required again from 10/15 20:25 | Normal |
| zSend and system emails (including login links) | 10/15 20:00–22:02 | Restored; zSend keys must be created again |
| GitHub sign-in and deployments | 10/15 18:54–22:49 | Restored |
| Builds | 10/15 20:05–22:56; China regions until 10/16 01:44 | Restored |
| Database backups | 10/15 20:33–22:13 | Restored |
| GCP Dedicated Server management | 10/15 17:31–20:35 | Restored; web SSH only |
| Dedicated Server auto-renewal | Tencent Cloud 10/15 22:55–10/16 01:08, 154 failures | Restored; charges refunded as account balance |
| Tencent Cloud password reset and SSH login records | From 10/15 | Restored |
| Linode dedicated Kubernetes clusters | From 10/15 | Restored |
The attacker took two paths. Path A went from the shared cluster into Zeabur's AWS account and secrets management service. Path B got root access to GCP Dedicated Servers. On October 15, the two paths met inside Zeabur's internal network. The MITRE ATT&CK technique for each step is in the appendix.
These sign-ins happened on October 14, more than a day before Path A's earliest known read of production secrets (October 15 at 14:52). The secrets read through Path A therefore cannot explain how Path B started. Between September 1 and 5, an unknown source also signed in to the same servers with the root password, reaching about 98 servers on September 5 alone. Whether this was the same attacker cannot be confirmed.
Our conclusion that the platform database was read comes from connection records at both ends of the internal network and from the database logs. All 29 database connections in this period map to this node, and we can trace each sign-in and query within them, 8,903 operation records in total.
On October 15 at 13:56, a user report led us to start the investigation. By then, about 36 hours had passed since the attacker first used the credentials (October 14 at 01:36), and the attack activity on October 14 alone had run for more than 16 hours.
No alert fired during this time:
About 4 hours after we started the investigation, we removed the attacker's internal network node. Our actions on October 15 and 16:
| Time (October 15) | Action |
|---|---|
| 14:43–15:56 | Allowed only Zeabur systems to connect to the shared cluster's admin interface |
| 15:32 | Revoked the cluster admin tokens that were used; rotated again at 21:47 |
| 17:17, 17:31 | Disabled the two GCP keys the attacker used |
| 17:58 | Removed the attacker's internal network node and revoked the credential that created it |
| 18:51 | Deleted the cluster backup access key |
| 18:54 | Rotated the GitHub App private key, payment service key, and GitHub OAuth secret |
| 18:55 | Removed root passwords from GCP server initialization settings |
| 20:05–21:22 | Disabled 24 AWS keys that had leaked or could not be ruled out, and replaced them with new keys with narrower permissions |
| 20:25 | Rotated the login signing key; all users were signed out |
| 20:34–20:36 | Removed permissions from the GCP servers' default service account; blocked public SSH to GCP servers |
| 20:47 | Revoked all 566 zSend API keys |
| 21:46 | Allowed only Zeabur systems to connect to Zeabur-managed dedicated clusters |
| 10/16 01:09 | Revoked the leaked Hetzner and DigitalOcean tokens |
Some of the credentials we put in place on the day of the response were later used by the attacker. The cause was the cluster's daily backup. It covers every resource in the cluster, secrets included, and on October 15 at 15:04 the attacker read the access key for those backups:
That the backup captured the new key and that the key was later used are both confirmed. That the attacker downloaded this backup is assessed. The key used at 20:30 may also have come from a backup the attacker had already obtained before 18:51.
From the start, the attacker held Zeabur's cluster admin tokens and several cloud keys. These credentials were kept in Zeabur's private configuration repository, in plaintext, as had long been the practice. The most likely explanation is that this repository leaked, but how it leaked cannot be confirmed. Our hypotheses are in Unconfirmed hypotheses.
This is Zeabur's second security incident in less than two months. Many users changed their setup following our guidance after August, and want to know why this still happened and whether the two incidents are related.
What we did after August. We rotated the internal keys confirmed as leaked at the time and disabled Legacy API Keys. In the product, projects on Dedicated Servers can move environment variables and config files to their own servers, delete the SSH credentials Zeabur stores, and view SSH login records. Our notices and announcements about the August incident also advised users to rotate credentials, delete the environment variables and config files stored on Zeabur, and move them to their own servers.
Why it still happened. The August rotation did not cover the cluster admin tokens and AWS keys stored in plaintext in the configuration repository, and the root passwords in GCP server initialization settings had not been fixed. Those are the credentials the attacker used this time. The August incident report said that "all internal admin keys have been disabled or rotated." That statement was incomplete, and we are correcting it here.
Zeabur will shut down on December 31, 2026, so this list includes only improvements we have already made.
| Item | Status |
|---|---|
| Revoke the cluster admin tokens that were used; allow only Zeabur systems to connect to the admin interface | Done |
| Remove root passwords from GCP server initialization settings; block public SSH | Done |
| Replace AWS keys with new keys with narrower permissions | Done |
| Allow only specific services to connect to the platform database | Done |
| Stop storing plaintext secrets in cluster backups; keep backup keys separate from other secrets | Done |
| Add alerts for unusual use of admin access, commands run inside containers, bulk reads of secrets or databases, new nodes joining the internal network, and cloud keys used from unfamiliar sources | Partly done |
With the records available, we still could not determine the following when we finalized this report. We treat any data and credentials where access cannot be ruled out as leaked.
31.57.201.201, which signed in to GCP Dedicated Servers with the root password in early September, was the same attacker.These are the explanations we consider most likely. Indirect evidence supports them, but there are no direct records, so do not cite them as fact. As of this final report, none has been proven or disproven.
103.237.102.191: browsed Zeabur without signing in on October 10 at 18:27, and accessed the shared cluster with an admin token on October 14.23.106.46.239: made a large number of unauthenticated attempts against the Zeabur API from October 12 at 12:52, attempted SSH sign-ins to Dedicated Servers on October 13, and first used the leaked AWS key on October 14 at 01:36.| Time (UTC) | Event |
|---|---|
| January 10, 2024 | Shared cluster admin token created with no expiry |
| January 20, 2026 | Admin token written in plaintext to the configuration repository |
| August 27 | GitHub App private key read during the August incident; its link to this incident is a hypothesis |
| August 30, September 2 | Configuration repository downloaded as an archive with an employee's GitHub authorization; who downloaded it cannot be confirmed |
| August 31 | GitHub App private key replaced; plaintext credentials in the configuration repository not rotated |
| September 1–5 | An unknown source signed in to about 98 GCP Dedicated Servers with the root password |
| September 3 | Root passwords found in GCP server initialization settings; not fixed before the incident |
| October 10, 18:27 | An IP later used to abuse credentials first appeared in Zeabur API access logs (not signed in) |
| October 13, 21:27 | Attacker IP attempted SSH sign-ins to 3 Dedicated Servers until 23:04; all failed |
| October 14, 01:36 | Attacker first used a Zeabur AWS key |
| October 14, 01:40 | Attacker first accessed the shared cluster with an admin token |
| October 14, 12:39 | Attacker read the settings and secrets of all services on the shared cluster |
| October 14, 13:40 | Attacker began reading data inside database containers and began signing in to GCP Dedicated Servers |
| October 14, 17:04 | Last command inside a database container |
| October 15, 13:56 | Investigation started after a user report |
| October 15, 14:43 | Began restricting connection sources for the shared cluster admin interface |
| October 15, 14:52 | Attacker began reading about 53 production secrets, until 16:51 |
| October 15, 15:02 | A deploy key for a decommissioned service read the configuration repository (hypothesized to be the attacker) |
| October 15, 15:30 | Attacker joined a node to Zeabur's internal network |
| October 15, 15:42 | Attacker downloaded user database backups from Zeabur storage |
| October 15, 16:06 | Attacker searched the obtained data for API keys, until 18:13 |
| October 15, 16:10 | Attacker began reading the platform database, until 16:47 |
| October 15, 16:12 | Attacker began calling the API as impersonated accounts, until 17:19 |
| October 15, 17:58 | Attacker's internal network node removed |
| October 15, 19:50 | Attacker's second wave of sign-ins to GCP Dedicated Servers, until 20:36 |
| October 15, 20:25 | Login signing key rotated; all users signed out |
| October 15, 20:36 | Public SSH to GCP Dedicated Servers blocked; attacker sign-ins stopped |
| October 15, 20:48 | Status page updated to show the platform database and Dedicated Servers were also affected |
| October 15, 21:01 | Attacker attempted to access shared cluster nodes and was denied |
| October 15, 21:05 | Last attacker activity observed (AWS) |
| October 16, 01:09 | Hetzner and DigitalOcean tokens revoked |
If you find any of these indicators in your systems or in your service providers' logs, treat the related credentials as leaked and contact us. The attacker made heavy use of rotating proxy servers, so the table lists only representative addresses. Confidence uses the STIX 0–100 scale: Confirmed is 85, Assessed is 60, and Cannot be confirmed is 30. A machine-readable version is in the STIX 2.1 file, where the IP indicators are valid until January 13, 2027.
| Type | Indicator | Seen in | Confidence |
|---|---|---|---|
| IP | 23.106.46.239 | Cluster access, cloud APIs, SSH sign-ins | 85 |
| IP | 102.244.78.57 | Cloud APIs, GCP settings changes | 85 |
| IP | 103.237.102.191 | Cluster access, cloud APIs | 85 |
| IP | 103.112.139.162 | First use of a cluster admin token | 85 |
| IP | 45.146.232.28 | AWS key validation | 85 |
| IP | 216.98.11.198, 45.58.38.175 | Dedicated Server SSH sign-ins | 85 |
| IP | 52.220.72.188 | Callback address of the program planted in PostgreSQL | 85 |
| IP | 31.57.201.201 | Root password sign-ins to GCP Dedicated Servers in early September; link to this incident cannot be confirmed | 30 |
| SSH key | Comment *@zeabur-pentest, fingerprint SHA256:EdBc0uephoOMemIRKK0SRV2TRR45n52tJm1yErVU1iM | Key the attacker added to Dedicated Servers | 85 |
| User-Agent | Contains both Boto3/1.43.111 and os/linux#6.12.86+deb13-amd64 | Client the attacker used with AWS keys. Matching on this alone gives false positives, so combine it with the source IP and the key | 60 |
Ordered by MITRE ATT&CK tactic.
| Tactic | Technique | Section |
|---|---|---|
| Initial Access | T1078.004 Valid Accounts: Cloud Accounts | Path A, step 1 |
| Initial Access | T1133 External Remote Services | Where the two paths met, step 1 |
| Execution | T1609 Container Administration Command | Path A, step 3 |
| Persistence | T1098.004 Account Manipulation: SSH Authorized Keys | Path B, steps 2 and 3 |
| Defense Evasion | T1578.002 Modify Cloud Compute Infrastructure: Create Cloud Instance | GCP Dedicated Servers |
| Defense Evasion | T1578.001 Modify Cloud Compute Infrastructure: Create Snapshot | GCP Dedicated Servers |
| Credential Access | T1552.001 Unsecured Credentials: Credentials In Files | Path A, step 1 |
| Credential Access | T1552.007 Unsecured Credentials: Container API | Path A, step 2 |
| Credential Access | T1552 Unsecured Credentials | Path B, step 1 |
| Credential Access | T1555.006 Credentials from Password Stores: Cloud Secrets Management Stores | Path A, step 5 |
| Credential Access | T1606 Forge Web Credentials | Account impersonation |
| Credential Access | T1110 Brute Force (hypothesis) | SSH attempts before October 14 |
| Discovery | T1580 Cloud Infrastructure Discovery | Zeabur internal systems |
| Lateral Movement | T1021.004 Remote Services: SSH | Path B, step 1 |
| Collection | T1530 Data from Cloud Storage | Path A, step 4 |
| Collection | T1213.006 Data from Information Repositories: Databases | Where the two paths met, step 2 |
| Impact | T1496.004 Resource Hijacking: Cloud Service Hijacking (unsuccessful) | Zeabur internal systems |
If you need help, or notice unusual access or charges you can't explain, contact us through Zeabur Support. Before you contact us, revoke the related credentials and share only masked information. Don't post keys or passwords that are still valid in tickets or public channels.
Leaked credentials can be misused to run up charges on your accounts, and we are deeply sorry for any costs this causes you. Given its current finances, Zeabur cannot pay third-party service costs that result from this incident. Most cloud and API providers have a dispute or waiver process, and you can attach this report to explain what happened. If a provider asks for other evidence, tell us in a ticket and we will do our best to provide it. Account balance refunds are not affected by this incident; see Zeabur follow-up on the October 2026 security incident.
Zeabur has announced that it will shut down on December 31, 2026, which is an operational decision. Until then, we will keep handling support requests related to this incident.
We learned of this incident from a user report about 36 hours after the attacker started using the credentials. Protecting the credentials you stored on Zeabur was our responsibility, and we failed to do it. We apologize to every affected user.
The Zeabur team