A Python script that scans websites for exposed Supabase JWT tokens, enumerates accessible database tables, and analyzes them for sensitive data exposure. The script automatically detects sensitive information (emails, passwords, API keys, PII, financial data, etc.) and classifies vulnerability levels to identify which tables pose security risks.
Related blog post: How rep+ Helped Me Identify a Critical Supabase JWT Exposure
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activatepip install -r requirements.txtpython supabase-exposure-check.py --url https://example.comCreate a sites.txt file with one URL per line:
https://example.com
https://another-site.com
Then run:
python supabase-exposure-check.py --file sites.txt
# Or simply (if sites.txt exists):
python supabase-exposure-check.pyThe script will:
- Scan the website's JavaScript files for exposed Supabase JWTs
- Enumerate all REST-exposed tables
- Test whether each table was readable
- Safely dump readable data as JSON (read-only)
Output is saved to the output/ directory (by default), organized by domain, with tables in a tables/ subdirectory.
--url: Single website URL to scan--file,-f: File containing list of URLs to scan (one per line)--output,-o: Output directory (default:output)
$ python3 supabase-exposure-check.py -f sites.txt -o output
[*] Scanning 2 site(s)
π Scanning https://www.example-site.com/
π¨ VULNERABLE: Supabase JWT exposed
[+] Found 21 tables
[+] triage_tickets: 0 rows - Public data (no sensitive fields detected)
[+] brands: 7 rows - Public data (no sensitive fields detected)
[-] lms_user_progress: blocked
π¨ projects_with_details: 539 rows - VULNERABLE (high) - Sensitive fields: user_id, supabase_anon_key, supabase_service_role_key, user_email
π¨ users: 488 rows - VULNERABLE (high) - Sensitive fields: email
β οΈ VULNERABILITY SUMMARY:
- Critical: 0 table(s)
- High: 2 table(s)
- Medium: 0 table(s)
- Total vulnerable: 2/16 accessible tables
π Scanning https://another-example.com/
π¨ VULNERABLE: Supabase JWT exposed
[+] Found 8 tables
π¨ newsletters: 389 rows - VULNERABLE (medium) - Sensitive fields: location
[+] newsletter_categories: 897 rows - Public data (no sensitive fields detected)
π¨ users: 495 rows - VULNERABLE (high) - Sensitive fields: email, location
π¨ upvotes: 3513 rows - VULNERABLE (medium) - Sensitive fields: user_id
β οΈ VULNERABILITY SUMMARY:
- Critical: 0 table(s)
- High: 1 table(s)
- Medium: 3 table(s)
- Total vulnerable: 4/8 accessible tablesThe script automatically identifies:
- Public tables: Safe to expose (no sensitive fields detected)
- Blocked tables: Protected by Row Level Security (RLS) policies
- Vulnerable tables: Contain sensitive information (emails, passwords, API keys, PII, etc.)
Vulnerability levels:
- Critical: Contains passwords, API keys, secrets, tokens, credit cards, SSN
- High: Contains emails, phone numbers, or other high-value PII
- Medium: Contains other sensitive data (user IDs, locations, etc.)
For each scanned website, the script creates:
- A directory named after the domain in the
output/folder findings.json: Contains discovered JWTs and Supabase URLssummary.json: Summary of all tested tables and their accessibility statustables/subdirectory: Individual JSON files for each readable table