How I dumped 14,000 crypto traders from a scanner app with exposed Supabase keys
How I dumped 14,000 crypto traders from a scanner app with exposed Supabase keys
CryptoXScanner is a crypto trading tool. You sign up, connect your exchange accounts, set up Telegram alerts, and it watches the markets for you.
The entire user database was readable through an unauthenticated Supabase API call. 14,021 users, full records, no restrictions.
The setup
The site uses Supabase as its backend with Auth0 for authentication. The Supabase anon key was in the frontend source, which is normal. What's not normal is that the key had unrestricted read access to every row in the users table.
One GET request:
GET /rest/v1/users?select=*&limit=1000&offset=0
Returns everything. Paginate through with offset and you have the full database in about 15 batches.
What leaked
Every user record contains:
| Field | Example |
|---|---|
| name | Real full names from Google OAuth |
| Personal Gmail, Hotmail, Yahoo, iCloud, Yandex accounts | |
| auth0_id | `google-oauth2 |
| telegram_id | Numeric Telegram user IDs |
| telegram_alert | Whether alerts are enabled |
| mexc_uid | MEXC exchange user IDs |
| created_at | Account creation timestamp |
The user base is heavily international. Lots of Turkish names (Mehmet, Emre, Mustafa), Arabic names, Russian, Indonesian, Pakistani users. Registration dates start February 2024 and run through early 2026.
The Auth0 IDs are particularly interesting. For Google OAuth users, the format google-oauth2|NUMERIC_ID contains the Google user ID, which can be used to look up Google profiles. For email/password users, the auth0|HEX format identifies them in Auth0's system.
The Telegram IDs are also worth noting. If someone has your Telegram numeric ID, they can use it to correlate your Telegram account with your real identity from this leak. A user named "klic klac" at klacklic29@gmail.com has Telegram ID 1471886557 with alerts turned on. That's enough to find them on Telegram and know their real email, and potentially what crypto positions they're watching.
The MEXC exchange UIDs, where present, link these accounts directly to a centralized exchange. Someone cross-referencing this data with other breaches could piece together trading activity.
No passwords, but that's not the point
Supabase stores password hashes in the internal auth.users table, which wasn't accessible with the anon key. And most users signed in through Google OAuth anyway, so there aren't that many password hashes to begin with.
But the combination of real name + email + Telegram ID + exchange UID is plenty. For 14,000 crypto traders, that's a phishing kit waiting to happen. You know who they are, how they trade, and how to reach them.
The fix
Enable Row Level Security on the users table. With Supabase, the anon key is expected to be public. RLS is what gates access.
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can only read own record"
ON users FOR SELECT
USING (auth.uid() = id);