Geph Security Incident Report: September 11, 2026
Summary
On September 11, 2026, an attacker used a database password that had been accidentally published on GitHub in 2021 to copy most of Geph's PostgreSQL account database.
For the vast majority of users, no sensitive personal information was leaked. Geph never asks for contact information to register, and we never store browsing history, card numbers, or Alipay / WeChat Pay accounts. As long as you never bought or received a gift card (and didn't use a legacy username containing your email address), the leaked data contains no email address, name, or other identifying information about you. The only thing you need to do is replace your account secret (see below).
-
When: from 01:28 UTC until the credential was revoked at 03:57 UTC. -
What was exposed: account secrets, legacy password hashes, payment records (amounts, timestamps, and transaction IDs, not card numbers or Alipay / WeChat Pay accounts), and 1,053 gift card recipient email addresses. -
What was not exposed: browsing history, traffic encryption keys, and payment card details, because Geph never stores them. -
Service impact: the export triggered a database-locking failure that disrupted the broker service from 01:58 to 03:44 UTC. -
Action required: update to Geph 5.9.0 and replace your account secret. Plus users who replace their secret receive 7 days of extra Plus time as compensation.
What information was leaked?
From database logs, we know for certain the following information was leaked. However, during the unauthorized access, queries that took under a second to fulfill were not logged, so the attacker could have accessed other small pieces of information without our knowledge.
See What we never stored for the information that could not have leaked.
Most notably, the following information was leaked:
-
Account credentials:
- Account secrets: all account secrets, in plaintext, and linked internal account IDs.
- Authentication tokens linked to account IDs.
- Legacy usernames, password hashes, and associated account IDs.
- Account metadata: login timestamps, and subscription tiers with start and end times.
-
Payment invoices: purchase amounts, timestamps, payment methods, and transaction references, linked to Geph accounts.
- Note: "payment records" here means internal billing data like invoice and transaction IDs only. It does not include bank card numbers, bank transaction numbers, credit card details, or Alipay / WeChat Pay accounts or transaction numbers. We never stored those, so they could not have leaked.
-
Gift card information:
- All 1,053 unique recipient email addresses.
- Gift card codes, sender names, purchasing accounts, and redemption data.
-
Obsolete infrastructure secrets for Geph 4: none of the leaked legacy credentials were active except for
bridge_secret, the broker's bridge-registration token. This token has since been replaced.
What we never stored
The following information was not leaked because it was never stored in our database:
- VPN browsing histories or encryption keys: Geph never stores per-user browsing history or tunnel encryption keys.
- User contact information: email, phone number, address, etc. Geph does not ask for any contact information to register an account, so there is none to store. Exceptions: gift card recipients' emails, and legacy usernames that contained the user's email address.
- Identifying payment details: bank account numbers, credit card details, and Alipay / WeChat Pay payment accounts are never stored.
What users should do
Geph account secrets generally does not allow the attacker to access any sensitive information. However, the attacker could log in with any existing user account at any time and consume users' bandwidth and devices limit.
But as long as you replace your account secret before the attacker does, your account will be secure from the attacker. We've designed a feature in version 5.9.0 that automates this process:
Replace your account secret
-
Update Geph to version 5.9.0. Geph will prompt you to replace your account secret:
Geph asks you to replace your account secret.
-
Save your new secret, confirm, and continue. Your old secret stops working, and your other devices will not continue to function.
Your new secret. (The secret shown is an example.) -
On each of your other devices, log in with your new secret. Geph detects that the old secret was replaced; choose "I replaced it on another device" and enter your new secret.
Geph notices the old secret no longer works.
Log in with the new secret from your first device. -
If you have a legacy username and password, they stop working once you replace your account secret. If you used that password on any other service, change it there.
Plus users: as compensation for the inconvenience, replacing your account secret adds 7 days of extra Plus time to your account.
If someone else replaced your secret
We currently do not detect any malicious account-manipulation behavior. However, if the attacker replaces your secret before you do, you will be logged out and not be able to log back in. If Geph shows "This secret was already replaced" and you did not replace it yourself, choose "I didn't do this", then:
- Free users: log out and create a new account.
-
Plus users: create a new account, then email
support@geph.ioto transfer your remaining Plus time. Include:- Your old account secret
- Your new account secret
- Proof of payment for your Plus plan
How it happened
How did the database credentials leak?
We discovered that the leaked credentials were accidentally uploaded to GitHub in this website billing source code file back in 2021.
The database connection settings in
racket/billing.rkt, as published on GitHub.
The database credentials did not change over the past 5 years; however, the September 11, 2026 intrusion is the only known unauthorized access of the Geph database.
What exactly happened?
The logs show unauthorized database access from two IP addresses.
One client seemed to be Navicat (a common database-management tool) and queried the database interactively, including a completed read from the legacy secrets table.
Another identified itself as pg_dump and attempted to export the entire database. Both authenticated with the administrative database credential. We do not know whether the two addresses were operated by the same person.
The export then caused a broker outage:
- The long-running whole-database export held a read lock on the exit-registry table.
- A few minutes later, the broker started a routine
VACUUM FULLmaintenance operation on that table. It requested an exclusive lock and waited behind the export. - Subsequent broker reads and writes queued behind the waiting maintenance operation.
- The blocked requests filled the broker's upstream connection capacity. Failures and retries rose sharply, producing large numbers of short-lived HTTPS connections.
- The host's network connection-tracking table filled, and the kernel began dropping packets.
Our team first noticed the full connection-tracking table and increased that table's capacity; this reduced the network symptoms but did not resolve the database lockup.
Broker RPC latency before, during, and after the outage.
During the outage:
- New connections, reconnections, and other broker-dependent operations were disrupted.
- Established tunnels continued forwarding traffic.
- Plus connections could have experienced reduced speeds, because bandwidth credits could not be replenished.
Terminating the waiting maintenance session at 03:40 UTC released the broker queries, and the export was terminated at 03:42. The broker had recovered by 03:44.
Who was responsible?
We only know that the attacker accessed the database from 2 Hong Kong IP addresses, one belonging to Alibaba Cloud and the other to StarCloud. These are cloud hosting addresses, so their location does not indicate where the attacker is. We refer to "the attacker" throughout this report, but we do not know whether one or more people were involved.
| Source IP | Client | AS number | Registered network |
|---|---|---|---|
154.31.217.202 |
pg_dump |
AS18186 | StarCloudGlobal-HK |
47.242.228.124 |
Navicat | AS45102 | ALIBABA CLOUD-HK |
Timeline
All times below are UTC on September 11, 2026.
| Time | Event | Actor |
|---|---|---|
| 01:28 | First recorded unauthorized database authentication from Navicat source; successful main-database sessions followed. | attacker |
| 01:51 | The unauthorized pg_dump export session connected. |
attacker |
| 01:58 | The exit-table maintenance operation became blocked behind the export, and broker queries accumulated. | Geph broker |
| 02:06 | The kernel began reporting a full network connection-tracking table. | Geph broker |
| 02:10 | Navicat completed a direct query of the secrets table. |
attacker |
| 03:40 | The waiting maintenance session was terminated; blocked broker queries resumed. | Geph team |
| 03:42 | The unauthorized pg_dump export session was terminated. |
Geph team |
| 03:44 | Recent response samples showed the broker had recovered. | Geph broker |
| 03:57 | The administrative database password was reset. | Geph team |
Remediation
Containment
- Removed the attacker's access. The database admin credentials were revoked at 03:57 UTC. We also disabled all non-admin database credentials, since they were accessible with admin privileges.
- Revoked the compromised bridge registration key, so that the attacker cannot insert false bridges to spy on users' traffic.
- Temporarily disabled user deletion, to prevent the attacker from sabotaging user accounts. So far we have not seen any malicious account manipulation. We will re-enable user deletion once most users have replaced their account secret.
- Account secret replacement in Geph 5.9.0 (see What users should do).
Hardening
- Account secrets are now stored hashed instead of in plaintext, so a future database compromise would not leak all account secrets like this time.
- Database access is restricted by IP whitelist.
- Legacy username/password login is being retired, as many user-created passwords are weak and their hashes are easily brute-forced.
Lessons we learned
This was the first intrusion into the Geph system that we are aware of. Three failures on our part made this possible:
- We published our main database admin credentials to a public GitHub repository, and did not discover it for 5 years.
- We stored account secrets in plaintext instead of hashing them. (We made this choice because account secrets are high-entropy and unguessable, removing one reason why password hashing is used)
- We did not restrict database access by IP address, which would have blocked access from all unauthorized IP addresses.
Because of our long-standing policy to collect as little data as possible (like not collecting any contact info at registration), and then minimally log whatever data we do collect, the database did not contain registration contact details, browsing history, or payment card information.
We sincerely apologize for the data leak, and all the trouble that replacing the account secret will cause all our users. We hope that by maintaining maximal transparency about what leaked and how everything was compromised, we can give our users the most clarity and best learn from past mistakes ourselves. We are continuing to improve our database practices and system-wide defense to make Geph a more secure VPN.
-- @nullchinchilla + @thisbefruit, the Geph team












