Misconfigured Supabase RLS Exposes 45,000 Wallet Addresses and Enables Mass Data Deletion
The Risk
A crypto platform's database was accessible to anyone on the internet without logging in. An attacker could read over 45,000 customer wallet addresses and trading volumes, modify campaign leaderboards and prize allocations, and delete data across the majority of the database. Personal information including a phone number from an unpublished campaign was also exposed. No account or credentials were needed to access any of this.
The Vulnerability
The platform's campaign system used Supabase as its backend. The Supabase anon key (a public JWT embedded in the frontend JavaScript) grants the anonymous role. Row Level Security policies were intended to restrict access, but only INSERT was properly blocked. SELECT, UPDATE, and DELETE were left open on most tables.
The Attack
Wallet Addresses and Trading Volumes
GraphQL queries against the campaign stats tables returned 28,753 wallet addresses with exact trading volumes across 7 campaigns, covering both Solana and EVM wallets. A separate airdrop table contained 16,089 additional wallet addresses with token balances.
Personal Information
An unpublished draft campaign (marked as not visible) contained a phone number in an encoded field, classifiable as PII under both GDPR and local data protection regulations.
Full Permission Matrix
Testing confirmed the anonymous role's access across all 13 tables:
- SELECT: Allowed on all tables
- INSERT: Blocked (correct, returns row-level security violation)
- UPDATE: Allowed on campaign stats, airdrop data, user profiles, and other major tables
- DELETE: Allowed on 10+ tables
The fact that INSERT was blocked proves the developers intended to restrict anonymous access but the RLS policies were incomplete.
State-Changing Function Execution
Beyond CRUD operations, the anonymous role could execute Supabase RPC functions. A test call to a leaderboard reset function returned success, confirming anonymous users could trigger state-changing database operations.
The Impact
- 45,372 wallet addresses exposed with trading volumes and balances
- PII exposure from unpublished campaign data
- Leaderboard and prize manipulation via UPDATE access
- Campaign statistics tampering
- Mass data deletion across 10+ tables
- Anonymous execution of state-changing database functions
Remediation
- Apply deny-by-default RLS policies on all tables for the anonymous role
- Audit all RPC functions for anonymous accessibility
- Restrict or disable anonymous GraphQL access
- Disable GraphQL introspection for the anonymous role
- Review all tables for unintended SELECT/UPDATE/DELETE permissions