DEV Community

Cover image for Introducing Supabomb: Open Source Supabase Penetration Testing
Victor Yrazusta Ibarra
Victor Yrazusta Ibarra

Posted on • Originally published at modernpentest.com

Introducing Supabomb: Open Source Supabase Penetration Testing

We're excited to announce the open source release of Supabomb, our specialized penetration testing tool for Supabase applications. It's the same tool that powers our automated Supabase security scanning at ModernPentest.

Why We Built Supabomb

Supabase has become the go-to backend for modern web applications. Its PostgreSQL foundation, real-time capabilities, and developer-friendly APIs make it incredibly powerful. But with that power comes security complexity.

After auditing dozens of Supabase applications, we noticed the same patterns repeatedly:

  • 23% of apps have exploitable RLS policies - Missing or misconfigured Row-Level Security is shockingly common
  • Most security tools miss Supabase-specific issues - Generic scanners don't understand PostgREST or RLS
  • Manual testing is tedious and incomplete - Checking every table and policy by hand takes hours

We built Supabomb to solve these problems. It's fast, thorough, and specifically designed for Supabase's unique architecture.

What Supabomb Does

Supabomb automates the entire Supabase security assessment workflow:

1. Credential Discovery

No need to manually copy API keys from your frontend code. Supabomb automatically discovers Supabase credentials from:

  • Web application URLs (parses HTML and JavaScript)
  • JavaScript bundles (including code-split and lazy-loaded modules)
  • HAR files from network traffic
  • Deep crawling with Katana integration
# Discover credentials from a live application
uv run supabomb discover --url https://your-app.com

# Deep discovery with JavaScript execution
uv run supabomb discover --url https://your-app.com --katana
Enter fullscreen mode Exit fullscreen mode

Sample output:

Crawling with Katana: https://demo-saas.example.com/
Max JS files: 50, Timeout: 120s

✓ Supabase instance found!
╭───────────────────┬───────────────────────────────────────────────────────╮
│ Project Reference │ abcdefghijklmnopqrst                                  │
│ URL               │ https://abcdefghijklmnopqrst.supabase.co              │
│ Anon Key          │ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzd... │
│ Source            │ Katana crawl of https://demo-saas.example.com/        │
│ Edge Functions    │ 4 discovered                                          │
╰───────────────────┴───────────────────────────────────────────────────────╯

Discovered Edge Functions:
╭─────┬─────────────────────────┬─────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────╮
│ #   │ Function Name           │ Arguments                                   │ Example                                                         │
├─────┼─────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 1   │ create-checkout-session │ plan=d, billing_period=m, additional_use... │ functions.invoke("create-checkout-session",{body:{plan:d,bil... │
│ 2   │ get-invoices            │ customerId=a, limit=20                      │ functions.invoke("get-invoices",{body:{customerId:a.stripe_c... │
│ 3   │ send-notification       │ userId=u, message=m, channel=c              │ functions.invoke("send-notification",{body:{userId:u,message... │
│ 4   │ generate-report         │ reportType=t, startDate=s, endDate=e        │ functions.invoke("generate-report",{body:{reportType:t,start... │
╰─────┴─────────────────────────┴─────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────╯

💾 Credentials saved to .supabomb.json
Enter fullscreen mode Exit fullscreen mode

2. Resource Enumeration

Once credentials are discovered, Supabomb enumerates everything accessible:

uv run supabomb enum
Enter fullscreen mode Exit fullscreen mode

Sample output:


📋 Using cached credentials for abcdefghijklmnopqrst

Enumerating Supabase instance: abcdefghijklmnopqrst
✓ Connection successful

Tables:
╭─────────────────────┬──────┬─────────┬───────────╮
│ Name                │ Read │ Columns │ Anon Rows │
├─────────────────────┼──────┼─────────┼───────────┤
│ users               │ ✓    │ 12      │ 1,847     │
│ profiles            │ ✓    │ 8       │ 1,847     │
│ organizations       │ ✓    │ 6       │ 423       │
│ projects            │ ✓    │ 14      │ 2,156     │
│ tasks               │ ✓    │ 18      │ 15,432    │
│ comments            │ ✓    │ 7       │ 48,291    │
│ attachments         │ ✓    │ 9       │ 8,734     │
│ notifications       │ ✗    │ 11      │ N/A       │
│ api_keys            │ ✗    │ 8       │ N/A       │
│ audit_logs          │ ✗    │ 15      │ N/A       │
│ billing_info        │ ✓    │ 10      │ 423       │
│ subscriptions       │ ✓    │ 12      │ 398       │
│ invitations         │ ✓    │ 7       │ 156       │
│ webhooks            │ ✗    │ 9       │ N/A       │
│ settings            │ ✓    │ 5       │ 423       │
╰─────────────────────┴──────┴─────────┴───────────╯

RPC Functions:
╭─────────────────────────────┬────────────┬────────────╮
│ Name                        │ Accessible │ Parameters │
├─────────────────────────────┼────────────┼────────────┤
│ get_user_projects           │ ✓          │ args       │
│ get_org_members             │ ✓          │ args       │
│ admin_list_users            │ ✓          │ args       │
│ admin_delete_user           │ ✗          │ args       │
│ get_current_user_role       │ ✓          │ args       │
│ is_admin                    │ ✓          │ args       │
│ update_user_permissions     │ ✗          │ args       │
│ generate_api_key            │ ✗          │ args       │
│ validate_invitation         │ ✗          │ args       │
│ cleanup_expired_sessions    │ ✓          │ args       │
╰─────────────────────────────┴────────────┴────────────╯
Enter fullscreen mode Exit fullscreen mode

This reveals:

  • All accessible database tables with column information
  • RPC (Remote Procedure Call) functions
  • Storage buckets
  • Row counts (anonymous vs. authenticated comparison)

3. Security Testing

The core of Supabomb - automated security testing that covers:

uv run supabomb test
Enter fullscreen mode Exit fullscreen mode

What it tests:

  • RLS policy effectiveness on every table
  • Authentication configuration (is anonymous signup enabled?)
  • RPC function access control
  • Storage bucket permissions
  • Edge function JWT requirements

Sample output:


📋 Using cached credentials for abcdefghijklmnopqrst

Testing Supabase instance: abcdefghijklmnopqrst
✓ Connection successful

╭──────────────────────────────────────────────────────── Security Test Summary ────────────────────────────────────────────────────────────╮
│ Total Findings: 5                                                                                                                         │
│ Risk Score: 24                                                                                                                            │
│                                                                                                                                           │
│ Critical: 1                                                                                                                               │
│ High: 1                                                                                                                                   │
│ Medium: 2                                                                                                                                 │
│ Low: 1                                                                                                                                    │
│ Info: 0                                                                                                                                   │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Findings:

╭────────────────────────────────────────── 1. Table 'users' accessible without authentication ─────────────────────────────────────────────╮
│ Severity: CRITICAL                                                                                                                        │
│ Affected: Table: users (1,847 rows exposed)                                                                                               │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The 'users' table can be read by unauthenticated users using the anonymous API key. This exposes sensitive user data including emails,    │
│ names, and profile information.                                                                                                           │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Add RLS policies to restrict access:                                                                                                      │
│ - CREATE POLICY "Users can view own profile" ON users FOR SELECT USING (auth.uid() = id);                                                 │
│ - Ensure RLS is enabled: ALTER TABLE users ENABLE ROW LEVEL SECURITY;                                                                     │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭───────────────────────────────────── 2. RPC function 'admin_list_users' accessible with anonymous key ────────────────────────────────────╮
│ Severity: HIGH                                                                                                                            │
│ Affected: RPC: admin_list_users                                                                                                           │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The RPC function 'admin_list_users' can be called with the anonymous API key. This admin function returns user data and should require    │
│ authentication and admin role verification.                                                                                               │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Add authentication check at the start of the function:                                                                                    │
│ - IF auth.uid() IS NULL THEN RAISE EXCEPTION 'Not authenticated';                                                                         │
│ - Verify admin role before returning data                                                                                                 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭─────────────────────────────────────────────── 3. Anonymous signup is enabled ────────────────────────────────────────────────────────────╮
│ Severity: MEDIUM                                                                                                                          │
│ Affected: Auth API                                                                                                                        │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The Supabase instance allows anonymous users to create accounts. This may be intentional, but could lead to abuse if not properly         │
│ configured with email confirmation and rate limiting.                                                                                     │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Review signup configuration. Consider:                                                                                                    │
│ - Enabling email confirmation                                                                                                             │
│ - Implementing rate limiting                                                                                                              │
│ - Adding CAPTCHA protection                                                                                                               │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭────────────────────────────────────────── 4. RPC function 'is_admin' accessible with anonymous key ───────────────────────────────────────╮
│ Severity: MEDIUM                                                                                                                          │
│ Affected: RPC: is_admin                                                                                                                   │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The RPC function 'is_admin' can be called with the anonymous API key. While it only returns a boolean, it could be used to enumerate      │
│ admin users by testing different user IDs.                                                                                                │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Review the function's logic and ensure it only checks the current authenticated user's role.                                              │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭─────────────────────────────────────────────── 5. Storage bucket 'avatars' is public ─────────────────────────────────────────────────────╮
│ Severity: LOW                                                                                                                             │
│ Affected: Storage: avatars                                                                                                                │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The 'avatars' storage bucket allows public read access. This is common for profile pictures but verify no sensitive files are stored.     │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Confirm this is intentional and implement upload restrictions to prevent abuse.                                                           │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Enter fullscreen mode Exit fullscreen mode

4. Write Permission Testing

Beyond read access, Supabomb tests if data can be modified:

uv run supabomb test-write
Enter fullscreen mode Exit fullscreen mode

Sample output:

📋 Using cached credentials for abcdefghijklmnopqrst

Testing write permissions: abcdefghijklmnopqrst
✓ Connection successful
Mode: anonymous

✓ Testing 15 table(s)

                                          Write Permission Test Results
╭───────────────────┬────────┬────────┬────────┬──────────────────────────────────────────────────────────────────╮
│ Table             │ INSERT │ UPDATE │ DELETE │ Details                                                          │
├───────────────────┼────────┼────────┼────────┼──────────────────────────────────────────────────────────────────┤
│ users             │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ profiles          │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ organizations     │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ projects          │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ tasks             │ ✓      │ ✓      │ ✗      │ INSERT and UPDATE allowed! Row created with id: 847291           │
│ comments          │ ✓      │ ✗      │ ✗      │ INSERT allowed! Row created with id: 159372                      │
│ attachments       │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ notifications     │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied for table notifications  │
│ api_keys          │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied for table api_keys       │
│ audit_logs        │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied for table audit_logs     │
│ billing_info      │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ subscriptions     │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ invitations       │ ⚠      │ -      │ -      │ Insert possible but needs crafted data: missing org_id reference │
│ webhooks          │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied for table webhooks       │
│ settings          │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
╰───────────────────┴────────┴────────┴────────┴──────────────────────────────────────────────────────────────────╯

Legend: ✓ = Allowed, ✗ = Denied (RLS), ⚠ = Possible with crafted data, - = Not tested

Enter fullscreen mode Exit fullscreen mode

This intelligently:

  • Generates test data based on actual table schema
  • Respects referential integrity when testing
  • Distinguishes between RLS denials and validation errors
  • Automatically cleans up test data after testing

5. Authenticated Testing

Test how RLS policies differ between anonymous and authenticated users:

# Register a test user (with automatic email verification)
uv run supabomb signup --verify-email

# Subsequent commands automatically use cached auth session
uv run supabomb test
uv run supabomb query -t users

# Force anonymous access with --use-anon flag
uv run supabomb query -t users --use-anon
Enter fullscreen mode Exit fullscreen mode

6. Data Export

Export accessible data for evidence collection:

# Query specific table to JSON
uv run supabomb query -t users -o users.json

# Export to CSV
uv run supabomb query -t users -o users.csv -f csv

# Dump all accessible tables
uv run supabomb dump -o ./evidence/
Enter fullscreen mode Exit fullscreen mode

7. All-in-One Assessment

Run the complete workflow with a single command:

uv run supabomb all --url https://your-app.com -o report.json
Enter fullscreen mode Exit fullscreen mode

This executes: discovery → registration → enumeration → data dump, generating a comprehensive JSON report.

Additional options:

# Include write permission testing
uv run supabomb all --url https://your-app.com -o report.json --test-write

# Use Katana for deep JavaScript crawling
uv run supabomb all --url https://your-app.com -o report.json --katana
Enter fullscreen mode Exit fullscreen mode

Key Features That Set Supabomb Apart

Intelligent Credential Caching

Supabomb caches discovered credentials in ~/.supabomb.json. Once you've scanned an app, subsequent commands automatically use the cached credentials:

# First time: discover and cache
uv run supabomb discover --url https://app.com

# Later: just run commands (credentials auto-loaded)
uv run supabomb enum
uv run supabomb test
Enter fullscreen mode Exit fullscreen mode

Manage cached credentials:

# List all cached credentials
uv run supabomb cached

# Remove a specific project
uv run supabomb cached --remove abcdefghij

# Clear all cached credentials
uv run supabomb cached --clear
Enter fullscreen mode Exit fullscreen mode

Deep JavaScript Analysis

Many tools only scan inline scripts. Supabomb analyzes up to 50+ JavaScript files per scan, including:

  • Directly linked scripts
  • Dynamically imported modules
  • Code-split chunks
  • Lazy-loaded bundles
  • Next.js/React/Vue bundle formats

This catches credentials hidden in complex frontend builds.

Automatic Email Verification

When testing requires a verified account, Supabomb integrates with temporary email services:

uv run supabomb signup --verify-email
Enter fullscreen mode Exit fullscreen mode

Sample output:

✓ Email verification required - using temporary email service
Created temporary email: xyz123@mail.tm

Registering user...
⏳ Account created, waiting for verification email...
✓ Verification email received!
✓ Email verified successfully!
✓ Login successful!

┌──────────────┬──────────────────────────────────────────┐
│ Property     │ Value                                    │
├──────────────┼──────────────────────────────────────────┤
│ User ID      │ 550e8400-e29b-41d4-a716-446655440000     │
│ Email        │ xyz123@mail.tm                           │
│ Role         │ authenticated                            │
└──────────────┴──────────────────────────────────────────┘

💾 Session saved to .supabomb.json
Enter fullscreen mode Exit fullscreen mode

This automatically:

  1. Creates a temporary email address
  2. Registers with your Supabase project
  3. Waits for the verification email
  4. Clicks the verification link
  5. Caches the authenticated session

No manual intervention needed.

Side-by-Side Access Comparison

Instantly see what's exposed to anonymous vs. authenticated users:

┌────────────────┬───────────┬───────────────┐
│ Table          │ Anon Rows │ Auth Rows     │
├────────────────┼───────────┼───────────────┤
│ public_posts   │ 150       │ 150           │
│ user_profiles  │ 1,234     │ 1,234  ⚠️     │
│ private_data   │ 0         │ 42            │
│ admin_logs     │ 0         │ 0             │
└────────────────┴───────────┴───────────────┘
⚠️ Warning: user_profiles accessible without auth
Enter fullscreen mode Exit fullscreen mode

Edge Function Discovery

Unique to Supabomb: it extracts edge function invocations directly from JavaScript code and tests them:

uv run supabomb check-jwt -e send_email -e get_posts
Enter fullscreen mode Exit fullscreen mode

Sample output:

Checking edge functions: abcdefghijklmnopqrst

┌─────────────────────────┬──────────────────┬──────────────────────────┬──────────────┐
│ Function Name           │ Requires JWT     │ Accessible with Anon Key │ Status Code  │
├─────────────────────────┼──────────────────┼──────────────────────────┼──────────────┤
│ create-checkout-session │ Yes              │ No                       │ 401          │
│ get-invoices            │ Yes              │ No                       │ 401          │
│ send-notification       │ No               │ Yes                      │ 200          │
│ generate-report         │ No               │ Yes                      │ 200          │
└─────────────────────────┴──────────────────┴──────────────────────────┴──────────────┘
Enter fullscreen mode Exit fullscreen mode

This reveals which edge functions require JWT authentication and which are publicly accessible.

Installation

Supabomb requires Python 3.13+ and uses uv for dependency management:

# Clone the repository
git clone https://github.com/Victoratus/supabomb.git
cd supabomb

# Run with uv (handles dependencies automatically)
uv run supabomb --help
Enter fullscreen mode Exit fullscreen mode

For deep crawling features, install Katana:

go install github.com/projectdiscovery/katana/cmd/katana@latest
Enter fullscreen mode Exit fullscreen mode

Example Workflow

Here's a typical security assessment workflow:

# 1. Discover credentials from the target application
uv run supabomb discover --url https://target-app.com --katana

# 2. See what resources are accessible (anonymous)
uv run supabomb enum

# 3. Run security tests
uv run supabomb test

# 4. If issues found, test write permissions
uv run supabomb test-write

# 5. Register for authenticated testing
uv run supabomb signup --verify-email

# 6. Re-run tests with authenticated session (automatic)
uv run supabomb enum
uv run supabomb test

# 7. Export evidence
uv run supabomb dump -o ./evidence/
Enter fullscreen mode Exit fullscreen mode

Responsible Use

Supabomb is designed for authorized security assessments only. Always ensure you have:

  • Written authorization from the application owner
  • Permission to test the specific Supabase project
  • Understanding of applicable laws in your jurisdiction

Never use this tool against applications you don't own or have explicit permission to test.

How It Powers ModernPentest

Supabomb is the foundation of our Supabase security scanning at ModernPentest. Our AI agents use Supabomb as their primary tool for:

  • Automated RLS policy analysis
  • Storage bucket permission auditing
  • PostgREST API security testing
  • Continuous monitoring for configuration drift

The difference? ModernPentest adds:

  • AI-powered analysis - Our agents interpret findings and prioritize by actual risk
  • Continuous scanning - Automated weekly/daily scans catch regressions
  • SOC 2 reports - Auditor-ready documentation generated automatically
  • Remediation guidance - Specific fix recommendations for each finding

If you want manual control, use Supabomb directly. If you want automated, continuous security with compliance reporting, try ModernPentest.

Get Started

The code is available on GitHub:

github.com/Victoratus/supabomb

Star the repo, try it on your projects, and let us know what you find. We welcome contributions, bug reports, and feature requests.

For comprehensive coverage of common Supabase security issues, check out our guide: 10 Common Supabase Security Misconfigurations.


Supabomb is part of our commitment to open source security tooling. Follow us for more tools and guides on securing modern web applications.

Top comments (0)