<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Victor Yrazusta Ibarra</title>
    <description>The latest articles on Forem by Victor Yrazusta Ibarra (@victor_yrazusta).</description>
    <link>https://forem.com/victor_yrazusta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3652549%2Feac1c43b-1e7a-4698-a42e-14605292b8b4.png</url>
      <title>Forem: Victor Yrazusta Ibarra</title>
      <link>https://forem.com/victor_yrazusta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/victor_yrazusta"/>
    <language>en</language>
    <item>
      <title>Introducing Firebomb: Open Source Firebase Penetration Testing</title>
      <dc:creator>Victor Yrazusta Ibarra</dc:creator>
      <pubDate>Sat, 10 Jan 2026 15:45:50 +0000</pubDate>
      <link>https://forem.com/victor_yrazusta/introducing-firebomb-open-source-firebase-penetration-testing-2ddn</link>
      <guid>https://forem.com/victor_yrazusta/introducing-firebomb-open-source-firebase-penetration-testing-2ddn</guid>
      <description>&lt;p&gt;We're releasing &lt;strong&gt;Firebomb&lt;/strong&gt;, our open source penetration testing tool for Firebase applications. It's the same tool powering our &lt;a href="https://modernpentest.com/firebase-pentesting" rel="noopener noreferrer"&gt;automated Firebase security scanning&lt;/a&gt; at ModernPentest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Firebase Security Problem
&lt;/h2&gt;

&lt;p&gt;Firebase makes it incredibly easy to build applications. Point your client SDK at Google's infrastructure, write some security rules, and you have a scalable backend in minutes.&lt;/p&gt;

&lt;p&gt;But that ease of development has created an epidemic of insecure applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;916 Firebase websites exposed 125 million user records in 2024&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;31% of Firebase apps have exploitable security rules&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Most developers deploy with test mode rules and never update them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generic security scanners don't understand Firebase's unique architecture—Firestore rules, RTDB permissions, Cloud Storage ACLs, the relationship between client SDKs and security rules. They miss the vulnerabilities that actually matter.&lt;/p&gt;

&lt;p&gt;Firebomb changes that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Firebomb Does
&lt;/h2&gt;

&lt;p&gt;Firebomb is a comprehensive security testing framework specifically for Firebase. It automates the complete penetration testing workflow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Configuration Discovery
&lt;/h3&gt;

&lt;p&gt;Firebomb automatically extracts Firebase credentials from web applications—no manual copying needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Discover from a live application&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://target-app.com

&lt;span class="c"&gt;# Deep recursive crawl (follows all JS files)&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://target-app.com &lt;span class="nt"&gt;--recursive&lt;/span&gt;

&lt;span class="c"&gt;# Validate discovered configs against Firebase APIs&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://target-app.com &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="nt"&gt;--validate&lt;/span&gt;

&lt;span class="c"&gt;# Parse from local files&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--file&lt;/span&gt; bundle.js
uv run firebomb discover &lt;span class="nt"&gt;--har&lt;/span&gt; traffic.har
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It finds credentials hidden in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inline JavaScript and HTML&lt;/li&gt;
&lt;li&gt;Bundled and minified scripts (webpack, Vite, esbuild)&lt;/li&gt;
&lt;li&gt;Code-split chunks and lazy-loaded modules&lt;/li&gt;
&lt;li&gt;Next.js/React/Vue/Angular build artifacts&lt;/li&gt;
&lt;li&gt;Source maps (extracts original source code)&lt;/li&gt;
&lt;li&gt;Environment variables (&lt;code&gt;NEXT_PUBLIC_FIREBASE_*&lt;/code&gt;, &lt;code&gt;VITE_FIREBASE_*&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Proactive Discovery (No Credentials Needed)
&lt;/h3&gt;

&lt;p&gt;Firebomb can discover Firebase projects without extracting credentials first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Probe by project ID&lt;/span&gt;
uv run firebomb probe &lt;span class="nt"&gt;--project-id&lt;/span&gt; suspected-project

&lt;span class="c"&gt;# Generate and probe from company name&lt;/span&gt;
uv run firebomb probe &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"Acme Corp"&lt;/span&gt;

&lt;span class="c"&gt;# Discover from domain&lt;/span&gt;
uv run firebomb probe &lt;span class="nt"&gt;--domain&lt;/span&gt; acme.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses DNS enumeration and direct API probing to find Firebase projects and check for misconfigurations—useful when you suspect Firebase usage but can't find the config.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Resource Enumeration
&lt;/h3&gt;

&lt;p&gt;Once configured, Firebomb discovers all accessible Firebase resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run firebomb enum &lt;span class="nt"&gt;--output&lt;/span&gt; enumeration.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firestore&lt;/strong&gt;: Collections, document counts, accessible fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realtime Database&lt;/strong&gt;: Paths, data structure, accessible nodes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage&lt;/strong&gt;: Buckets, file listings, ACL configurations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Functions&lt;/strong&gt;: Endpoints, authentication requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: Enabled providers, configuration settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Security Testing
&lt;/h3&gt;

&lt;p&gt;The core of Firebomb—automated vulnerability testing across all Firebase services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run firebomb &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; findings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Firestore Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public read/write access detection&lt;/li&gt;
&lt;li&gt;Missing authentication checks&lt;/li&gt;
&lt;li&gt;Cross-user data access vulnerabilities&lt;/li&gt;
&lt;li&gt;Document-level permission gaps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Realtime Database Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public path vulnerabilities&lt;/li&gt;
&lt;li&gt;Wildcard permission issues&lt;/li&gt;
&lt;li&gt;Root-level database exposure&lt;/li&gt;
&lt;li&gt;Path traversal risks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud Storage Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Publicly readable/writable buckets&lt;/li&gt;
&lt;li&gt;ACL misconfigurations&lt;/li&gt;
&lt;li&gt;Unauthorized file operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud Functions Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unauthenticated function access&lt;/li&gt;
&lt;li&gt;CORS misconfigurations&lt;/li&gt;
&lt;li&gt;Missing input validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anonymous authentication enabled&lt;/li&gt;
&lt;li&gt;Email verification requirements&lt;/li&gt;
&lt;li&gt;Password policy strength&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│ Security Testing Results                                        │
├─────────────────────────────────────────────────────────────────┤
│ Firestore: users                                                │
│   ✗ Collection publicly readable without authentication         │
│   Documents exposed: 1,847                                      │
│   Severity: CRITICAL                                            │
├─────────────────────────────────────────────────────────────────┤
│ Firestore: posts                                                │
│   ✓ Proper authentication required                              │
│   ✓ User-scoped access enforced                                 │
├─────────────────────────────────────────────────────────────────┤
│ Cloud Storage: user-uploads                                     │
│   ✗ Bucket publicly writable                                    │
│   Risk: Arbitrary file upload/malware hosting                   │
│   Severity: CRITICAL                                            │
├─────────────────────────────────────────────────────────────────┤
│ Authentication                                                  │
│   ⚠ Anonymous authentication enabled                            │
│   Risk: Unlimited account creation, resource abuse              │
│   Severity: MEDIUM                                              │
└─────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Authenticated Testing
&lt;/h3&gt;

&lt;p&gt;Test how permissions differ between anonymous and authenticated users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Auto-generate email with verification (recommended)&lt;/span&gt;
uv run firebomb signup &lt;span class="nt"&gt;--verify-email&lt;/span&gt;

&lt;span class="c"&gt;# Or use manual email/password&lt;/span&gt;
uv run firebomb signup &lt;span class="nt"&gt;--email&lt;/span&gt; tester@example.com &lt;span class="nt"&gt;--password&lt;/span&gt; SecurePass123!

&lt;span class="c"&gt;# Run tests with authentication&lt;/span&gt;
uv run firebomb &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--auth&lt;/span&gt;
uv run firebomb enum &lt;span class="nt"&gt;--auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals privilege escalation vulnerabilities—resources that should require authentication but don't, or resources accessible to any authenticated user instead of just the owner.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Data Extraction
&lt;/h3&gt;

&lt;p&gt;Query specific collections or paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Query specific Firestore collection&lt;/span&gt;
uv run firebomb query &lt;span class="nt"&gt;--collection&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; users.json

&lt;span class="c"&gt;# Query RTDB path&lt;/span&gt;
uv run firebomb query &lt;span class="nt"&gt;--path&lt;/span&gt; /messages &lt;span class="nt"&gt;--output&lt;/span&gt; messages.json

&lt;span class="c"&gt;# Export with limits&lt;/span&gt;
uv run firebomb query &lt;span class="nt"&gt;--collection&lt;/span&gt; orders &lt;span class="nt"&gt;--limit&lt;/span&gt; 100 &lt;span class="nt"&gt;--output&lt;/span&gt; sample.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Bulk Data Dump
&lt;/h3&gt;

&lt;p&gt;Export all accessible data for evidence collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dump all accessible Firebase data&lt;/span&gt;
uv run firebomb dump &lt;span class="nt"&gt;--output&lt;/span&gt; evidence.json

&lt;span class="c"&gt;# Dump with authentication&lt;/span&gt;
uv run firebomb dump &lt;span class="nt"&gt;--auth&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; auth-evidence.json

&lt;span class="c"&gt;# Dump specific collections only&lt;/span&gt;
uv run firebomb dump &lt;span class="nt"&gt;--firestore-only&lt;/span&gt; &lt;span class="nt"&gt;--collections&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt;,orders &lt;span class="nt"&gt;--output&lt;/span&gt; data.json

&lt;span class="c"&gt;# Limit documents per collection&lt;/span&gt;
uv run firebomb dump &lt;span class="nt"&gt;--limit&lt;/span&gt; 500 &lt;span class="nt"&gt;--output&lt;/span&gt; sample.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dump command fetches actual document contents from Firestore, full data trees from RTDB, and file listings from Cloud Storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Professional Reports
&lt;/h3&gt;

&lt;p&gt;Generate stakeholder-ready security assessments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# HTML report for executives&lt;/span&gt;
uv run firebomb report &lt;span class="nt"&gt;--format&lt;/span&gt; html &lt;span class="nt"&gt;--output&lt;/span&gt; assessment.html

&lt;span class="c"&gt;# JSON report for developers&lt;/span&gt;
uv run firebomb report &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;--output&lt;/span&gt; findings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reports include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executive summary with risk assessment&lt;/li&gt;
&lt;li&gt;Detailed findings with severity classification&lt;/li&gt;
&lt;li&gt;CWE and OWASP mapping&lt;/li&gt;
&lt;li&gt;Remediation guidance with code examples&lt;/li&gt;
&lt;li&gt;Evidence and proof of concept&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Smart Credential &amp;amp; Session Management
&lt;/h3&gt;

&lt;p&gt;Firebomb caches discovered configurations and authentication sessions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Discover and cache (default behavior)&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://app.com

&lt;span class="c"&gt;# Later: credentials auto-loaded&lt;/span&gt;
uv run firebomb enum
uv run firebomb &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# View cached configurations&lt;/span&gt;
uv run firebomb cached

&lt;span class="c"&gt;# View cached sessions&lt;/span&gt;
uv run firebomb cached &lt;span class="nt"&gt;--sessions&lt;/span&gt;

&lt;span class="c"&gt;# Remove specific project&lt;/span&gt;
uv run firebomb cached &lt;span class="nt"&gt;--remove&lt;/span&gt; my-project

&lt;span class="c"&gt;# Clear all cached data&lt;/span&gt;
uv run firebomb cached &lt;span class="nt"&gt;--clear&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comprehensive Service Coverage
&lt;/h3&gt;

&lt;p&gt;Unlike generic scanners, Firebomb understands all Firebase services:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;What Firebomb Tests&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Firestore&lt;/td&gt;
&lt;td&gt;Rules, collection access, cross-user data leakage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTDB&lt;/td&gt;
&lt;td&gt;Permissions, path traversal, wildcard rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Bucket ACLs, file type restrictions, public access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Functions&lt;/td&gt;
&lt;td&gt;Authentication, CORS, input validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Provider config, anonymous auth, MFA settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;DNS probing, API probing, framework detection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Severity Classification
&lt;/h3&gt;

&lt;p&gt;Findings are categorized by actual risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CRITICAL&lt;/strong&gt;: Complete data exposure, write access to all data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HIGH&lt;/strong&gt;: Significant data leakage, unauthorized access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MEDIUM&lt;/strong&gt;: Configuration weaknesses, potential abuse vectors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LOW&lt;/strong&gt;: Best practice violations, minor issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;INFO&lt;/strong&gt;: Documentation, recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remediation Guidance
&lt;/h3&gt;

&lt;p&gt;Every finding includes specific fix instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│ Finding: Firestore collection 'users' publicly readable         │
├─────────────────────────────────────────────────────────────────┤
│ Severity: CRITICAL                                              │
│ CWE: CWE-284 (Improper Access Control)                          │
│ OWASP: A01:2021 - Broken Access Control                         │
├─────────────────────────────────────────────────────────────────┤
│ Current Rules:                                                  │
│   match /users/{userId} {                                       │
│     allow read: if true;                                        │
│   }                                                             │
├─────────────────────────────────────────────────────────────────┤
│ Recommended Fix:                                                │
│   match /users/{userId} {                                       │
│     allow read: if request.auth != null                         │
│       &amp;amp;&amp;amp; request.auth.uid == userId;                            │
│   }                                                             │
└─────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Capabilities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Framework Auto-Detection
&lt;/h3&gt;

&lt;p&gt;Firebomb automatically detects and optimizes for modern frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt;: Parses &lt;code&gt;_buildManifest.js&lt;/code&gt;, follows chunk patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt;: Handles Create React App and custom builds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vue/Nuxt&lt;/strong&gt;: Detects Vue-specific bundle patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite&lt;/strong&gt;: Extracts from Vite build outputs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Angular&lt;/strong&gt;: Supports Angular CLI builds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deep JavaScript Analysis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Recursive crawling with configurable depth and file limits&lt;/li&gt;
&lt;li&gt;Webpack chunk extraction and following&lt;/li&gt;
&lt;li&gt;Source map parsing for original source code&lt;/li&gt;
&lt;li&gt;Environment variable pattern detection (&lt;code&gt;NEXT_PUBLIC_*&lt;/code&gt;, &lt;code&gt;VITE_*&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Minified code correlation for scattered config values&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Firebomb requires Python 3.11+ and uses &lt;code&gt;uv&lt;/code&gt; for dependency management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/ModernPentest/firebomb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;firebomb

&lt;span class="c"&gt;# Run with uv (handles dependencies automatically)&lt;/span&gt;
uv run firebomb &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example Workflow
&lt;/h2&gt;

&lt;p&gt;Here's a complete security assessment workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Discover Firebase configuration with validation&lt;/span&gt;
uv run firebomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://target-app.com &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="nt"&gt;--validate&lt;/span&gt;

&lt;span class="c"&gt;# 2. Or probe by company name if config not found&lt;/span&gt;
uv run firebomb probe &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"Target Company"&lt;/span&gt;

&lt;span class="c"&gt;# 3. Enumerate all resources&lt;/span&gt;
uv run firebomb enum &lt;span class="nt"&gt;--output&lt;/span&gt; enum.json

&lt;span class="c"&gt;# 4. Run security tests&lt;/span&gt;
uv run firebomb &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; findings.json

&lt;span class="c"&gt;# 5. Create test user with auto-verification&lt;/span&gt;
uv run firebomb signup &lt;span class="nt"&gt;--verify-email&lt;/span&gt;

&lt;span class="c"&gt;# 6. Test with authentication&lt;/span&gt;
uv run firebomb &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--auth&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; auth-findings.json

&lt;span class="c"&gt;# 7. Dump evidence from vulnerable resources&lt;/span&gt;
uv run firebomb dump &lt;span class="nt"&gt;--limit&lt;/span&gt; 100 &lt;span class="nt"&gt;--output&lt;/span&gt; evidence.json

&lt;span class="c"&gt;# 8. Generate professional report&lt;/span&gt;
uv run firebomb report &lt;span class="nt"&gt;--format&lt;/span&gt; html &lt;span class="nt"&gt;--output&lt;/span&gt; security-assessment.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Responsible Use
&lt;/h2&gt;

&lt;p&gt;Firebomb is designed for &lt;strong&gt;authorized security testing only&lt;/strong&gt;. Always ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Written authorization from the Firebase project owner&lt;/li&gt;
&lt;li&gt;Permission to test the specific project&lt;/li&gt;
&lt;li&gt;Understanding of applicable laws&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never use this tool against applications you don't own or have explicit permission to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Powers ModernPentest
&lt;/h2&gt;

&lt;p&gt;Firebomb is the foundation of our &lt;a href="https://dev.to/firebase-pentesting"&gt;Firebase security scanning&lt;/a&gt; at ModernPentest. Our AI agents use Firebomb as their primary tool for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated Firestore rules analysis&lt;/li&gt;
&lt;li&gt;RTDB permission auditing&lt;/li&gt;
&lt;li&gt;Cloud Storage ACL testing&lt;/li&gt;
&lt;li&gt;Continuous monitoring for configuration drift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ModernPentest adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered analysis&lt;/strong&gt; - Agents interpret findings and prioritize by actual business risk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous scanning&lt;/strong&gt; - Automated weekly/daily scans catch regressions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOC 2 reports&lt;/strong&gt; - Auditor-ready documentation generated automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remediation guidance&lt;/strong&gt; - Specific fix recommendations tailored to your codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For manual control, use Firebomb directly. For automated, continuous security with compliance reporting, &lt;a href="https://modernpentest.com/firebase-pentesting" rel="noopener noreferrer"&gt;try ModernPentest&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;The code is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ModernPentest/firebomb" rel="noopener noreferrer"&gt;github.com/ModernPentest/firebomb&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Star the repo, try it on your Firebase projects, and let us know what you find. We welcome contributions, bug reports, and feature requests.&lt;/p&gt;

&lt;p&gt;For a deep dive into Firebase security best practices, check out our guide: &lt;a href="https://modernpentest.com/blog/securing-firebase-in-production" rel="noopener noreferrer"&gt;Securing Firebase in Production&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Firebomb is part of our commitment to open source security tooling. Follow us for more tools and guides on securing modern web applications.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>cli</category>
      <category>firebase</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Introducing Supabomb: Open Source Supabase Penetration Testing</title>
      <dc:creator>Victor Yrazusta Ibarra</dc:creator>
      <pubDate>Mon, 08 Dec 2025 19:20:36 +0000</pubDate>
      <link>https://forem.com/victor_yrazusta/introducing-supabomb-open-source-supabase-penetration-testing-4dnb</link>
      <guid>https://forem.com/victor_yrazusta/introducing-supabomb-open-source-supabase-penetration-testing-4dnb</guid>
      <description>&lt;p&gt;We're excited to announce the open source release of &lt;strong&gt;Supabomb&lt;/strong&gt;, our specialized penetration testing tool for Supabase applications. It's the same tool that powers our &lt;a href="//modernpentest.com/supabase-security"&gt;automated Supabase security scanning&lt;/a&gt; at ModernPentest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Built Supabomb
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;After auditing dozens of Supabase applications, we noticed the same patterns repeatedly:&lt;/p&gt;

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

&lt;p&gt;We built Supabomb to solve these problems. It's fast, thorough, and specifically designed for Supabase's unique architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Supabomb Does
&lt;/h2&gt;

&lt;p&gt;Supabomb automates the entire Supabase security assessment workflow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Credential Discovery
&lt;/h3&gt;

&lt;p&gt;No need to manually copy API keys from your frontend code. Supabomb automatically discovers Supabase credentials from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web application URLs (parses HTML and JavaScript)&lt;/li&gt;
&lt;li&gt;JavaScript bundles (including code-split and lazy-loaded modules)&lt;/li&gt;
&lt;li&gt;HAR files from network traffic&lt;/li&gt;
&lt;li&gt;Deep crawling with Katana integration
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Discover credentials from a live application&lt;/span&gt;
uv run supabomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com

&lt;span class="c"&gt;# Deep discovery with JavaScript execution&lt;/span&gt;
uv run supabomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com &lt;span class="nt"&gt;--katana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;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:
╭─────┬─────────────────────────┬─────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────╮
│ &lt;span class="c"&gt;#   │ Function Name           │ Arguments                                   │ Example                                                         │&lt;/span&gt;
├─────┼─────────────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 1   │ create-checkout-session │ &lt;span class="nv"&gt;plan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;d, &lt;span class="nv"&gt;billing_period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;m, additional_use... │ functions.invoke&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"create-checkout-session"&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;body:&lt;span class="o"&gt;{&lt;/span&gt;plan:d,bil... │
│ 2   │ get-invoices            │ &lt;span class="nv"&gt;customerId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a, &lt;span class="nv"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20                      │ functions.invoke&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"get-invoices"&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;body:&lt;span class="o"&gt;{&lt;/span&gt;customerId:a.stripe_c... │
│ 3   │ send-notification       │ &lt;span class="nv"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;u, &lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;m, &lt;span class="nv"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c              │ functions.invoke&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"send-notification"&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;body:&lt;span class="o"&gt;{&lt;/span&gt;userId:u,message... │
│ 4   │ generate-report         │ &lt;span class="nv"&gt;reportType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;t, &lt;span class="nv"&gt;startDate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;s, &lt;span class="nv"&gt;endDate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;e        │ functions.invoke&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"generate-report"&lt;/span&gt;,&lt;span class="o"&gt;{&lt;/span&gt;body:&lt;span class="o"&gt;{&lt;/span&gt;reportType:t,start... │
╰─────┴─────────────────────────┴─────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────╯

💾 Credentials saved to .supabomb.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Resource Enumeration
&lt;/h3&gt;

&lt;p&gt;Once credentials are discovered, Supabomb enumerates everything accessible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb enum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
📋 Using cached credentials &lt;span class="k"&gt;for &lt;/span&gt;abcdefghijklmnopqrst

Enumerating Supabase instance: abcdefghijklmnopqrst
✓ Connection successful

Tables:
╭─────────────────────┬──────┬─────────┬───────────╮
│ Name                │ Read │ Columns │ Anon Rows │
├─────────────────────┼──────┼─────────┼───────────┤
│ &lt;span class="nb"&gt;users&lt;/span&gt;               │ ✓    │ 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       │
╰─────────────────────────────┴────────────┴────────────╯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All accessible database tables with column information&lt;/li&gt;
&lt;li&gt;RPC (Remote Procedure Call) functions&lt;/li&gt;
&lt;li&gt;Storage buckets&lt;/li&gt;
&lt;li&gt;Row counts (anonymous vs. authenticated comparison)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Security Testing
&lt;/h3&gt;

&lt;p&gt;The core of Supabomb - automated security testing that covers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it tests:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RLS policy effectiveness on every table&lt;/li&gt;
&lt;li&gt;Authentication configuration (is anonymous signup enabled?)&lt;/li&gt;
&lt;li&gt;RPC function access control&lt;/li&gt;
&lt;li&gt;Storage bucket permissions&lt;/li&gt;
&lt;li&gt;Edge function JWT requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
📋 Using cached credentials &lt;span class="k"&gt;for &lt;/span&gt;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 &lt;span class="s1"&gt;'users'&lt;/span&gt; accessible without authentication ─────────────────────────────────────────────╮
│ Severity: CRITICAL                                                                                                                        │
│ Affected: Table: &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;1,847 rows exposed&lt;span class="o"&gt;)&lt;/span&gt;                                                                                               │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The &lt;span class="s1"&gt;'users'&lt;/span&gt; table can be &lt;span class="nb"&gt;read &lt;/span&gt;by unauthenticated &lt;span class="nb"&gt;users &lt;/span&gt;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 &lt;span class="s2"&gt;"Users can view own profile"&lt;/span&gt; ON &lt;span class="nb"&gt;users &lt;/span&gt;FOR SELECT USING &lt;span class="o"&gt;(&lt;/span&gt;auth.uid&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                                 │
│ - Ensure RLS is enabled: ALTER TABLE &lt;span class="nb"&gt;users &lt;/span&gt;ENABLE ROW LEVEL SECURITY&lt;span class="p"&gt;;&lt;/span&gt;                                                                     │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

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

╭─────────────────────────────────────────────── 3. Anonymous signup is enabled ────────────────────────────────────────────────────────────╮
│ Severity: MEDIUM                                                                                                                          │
│ Affected: Auth API                                                                                                                        │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The Supabase instance allows anonymous &lt;span class="nb"&gt;users &lt;/span&gt;to create accounts. This may be intentional, but could lead to abuse &lt;span class="k"&gt;if &lt;/span&gt;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 &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="s1"&gt;'is_admin'&lt;/span&gt; accessible with anonymous key ───────────────────────────────────────╮
│ Severity: MEDIUM                                                                                                                          │
│ Affected: RPC: is_admin                                                                                                                   │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The RPC &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="s1"&gt;'is_admin'&lt;/span&gt; can be called with the anonymous API key. While it only returns a boolean, it could be used to enumerate      │
│ admin &lt;span class="nb"&gt;users &lt;/span&gt;by testing different user IDs.                                                                                                │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Review the &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="s1"&gt;'s logic and ensure it only checks the current authenticated user'&lt;/span&gt;s role.                                              │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

╭─────────────────────────────────────────────── 5. Storage bucket &lt;span class="s1"&gt;'avatars'&lt;/span&gt; is public ─────────────────────────────────────────────────────╮
│ Severity: LOW                                                                                                                             │
│ Affected: Storage: avatars                                                                                                                │
│                                                                                                                                           │
│ Description:                                                                                                                              │
│ The &lt;span class="s1"&gt;'avatars'&lt;/span&gt; storage bucket allows public &lt;span class="nb"&gt;read &lt;/span&gt;access. This is common &lt;span class="k"&gt;for &lt;/span&gt;profile pictures but verify no sensitive files are stored.     │
│                                                                                                                                           │
│ Recommendation:                                                                                                                           │
│ Confirm this is intentional and implement upload restrictions to prevent abuse.                                                           │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Write Permission Testing
&lt;/h3&gt;

&lt;p&gt;Beyond read access, Supabomb tests if data can be modified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb test-write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;📋 Using cached credentials &lt;span class="k"&gt;for &lt;/span&gt;abcdefghijklmnopqrst

Testing write permissions: abcdefghijklmnopqrst
✓ Connection successful
Mode: anonymous

✓ Testing 15 table&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt;

                                          Write Permission Test Results
╭───────────────────┬────────┬────────┬────────┬──────────────────────────────────────────────────────────────────╮
│ Table             │ INSERT │ UPDATE │ DELETE │ Details                                                          │
├───────────────────┼────────┼────────┼────────┼──────────────────────────────────────────────────────────────────┤
│ &lt;span class="nb"&gt;users&lt;/span&gt;             │ ✗      │ -      │ -      │ 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 &lt;span class="nb"&gt;id&lt;/span&gt;: 847291           │
│ comments          │ ✓      │ ✗      │ ✗      │ INSERT allowed! Row created with &lt;span class="nb"&gt;id&lt;/span&gt;: 159372                      │
│ attachments       │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
│ notifications     │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied &lt;span class="k"&gt;for &lt;/span&gt;table notifications  │
│ api_keys          │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied &lt;span class="k"&gt;for &lt;/span&gt;table api_keys       │
│ audit_logs        │ ✗      │ -      │ -      │ Insert denied by RLS: permission denied &lt;span class="k"&gt;for &lt;/span&gt;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 &lt;span class="k"&gt;for &lt;/span&gt;table webhooks       │
│ settings          │ ✗      │ -      │ -      │ Insert denied by RLS: new row violates row-level security policy │
╰───────────────────┴────────┴────────┴────────┴──────────────────────────────────────────────────────────────────╯

Legend: ✓ &lt;span class="o"&gt;=&lt;/span&gt; Allowed, ✗ &lt;span class="o"&gt;=&lt;/span&gt; Denied &lt;span class="o"&gt;(&lt;/span&gt;RLS&lt;span class="o"&gt;)&lt;/span&gt;, ⚠ &lt;span class="o"&gt;=&lt;/span&gt; Possible with crafted data, - &lt;span class="o"&gt;=&lt;/span&gt; Not tested

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This intelligently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates test data based on actual table schema&lt;/li&gt;
&lt;li&gt;Respects referential integrity when testing&lt;/li&gt;
&lt;li&gt;Distinguishes between RLS denials and validation errors&lt;/li&gt;
&lt;li&gt;Automatically cleans up test data after testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Authenticated Testing
&lt;/h3&gt;

&lt;p&gt;Test how RLS policies differ between anonymous and authenticated users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Register a test user (with automatic email verification)&lt;/span&gt;
uv run supabomb signup &lt;span class="nt"&gt;--verify-email&lt;/span&gt;

&lt;span class="c"&gt;# Subsequent commands automatically use cached auth session&lt;/span&gt;
uv run supabomb &lt;span class="nb"&gt;test
&lt;/span&gt;uv run supabomb query &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt;

&lt;span class="c"&gt;# Force anonymous access with --use-anon flag&lt;/span&gt;
uv run supabomb query &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="nt"&gt;--use-anon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Data Export
&lt;/h3&gt;

&lt;p&gt;Export accessible data for evidence collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Query specific table to JSON&lt;/span&gt;
uv run supabomb query &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; users.json

&lt;span class="c"&gt;# Export to CSV&lt;/span&gt;
uv run supabomb query &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;users&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; users.csv &lt;span class="nt"&gt;-f&lt;/span&gt; csv

&lt;span class="c"&gt;# Dump all accessible tables&lt;/span&gt;
uv run supabomb dump &lt;span class="nt"&gt;-o&lt;/span&gt; ./evidence/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. All-in-One Assessment
&lt;/h3&gt;

&lt;p&gt;Run the complete workflow with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb all &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com &lt;span class="nt"&gt;-o&lt;/span&gt; report.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This executes: discovery → registration → enumeration → data dump, generating a comprehensive JSON report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional options:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Include write permission testing&lt;/span&gt;
uv run supabomb all &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com &lt;span class="nt"&gt;-o&lt;/span&gt; report.json &lt;span class="nt"&gt;--test-write&lt;/span&gt;

&lt;span class="c"&gt;# Use Katana for deep JavaScript crawling&lt;/span&gt;
uv run supabomb all &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com &lt;span class="nt"&gt;-o&lt;/span&gt; report.json &lt;span class="nt"&gt;--katana&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Features That Set Supabomb Apart
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Intelligent Credential Caching
&lt;/h3&gt;

&lt;p&gt;Supabomb caches discovered credentials in &lt;code&gt;~/.supabomb.json&lt;/code&gt;. Once you've scanned an app, subsequent commands automatically use the cached credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First time: discover and cache&lt;/span&gt;
uv run supabomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://app.com

&lt;span class="c"&gt;# Later: just run commands (credentials auto-loaded)&lt;/span&gt;
uv run supabomb enum
uv run supabomb &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Manage cached credentials:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all cached credentials&lt;/span&gt;
uv run supabomb cached

&lt;span class="c"&gt;# Remove a specific project&lt;/span&gt;
uv run supabomb cached &lt;span class="nt"&gt;--remove&lt;/span&gt; abcdefghij

&lt;span class="c"&gt;# Clear all cached credentials&lt;/span&gt;
uv run supabomb cached &lt;span class="nt"&gt;--clear&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deep JavaScript Analysis
&lt;/h3&gt;

&lt;p&gt;Many tools only scan inline scripts. Supabomb analyzes up to 50+ JavaScript files per scan, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directly linked scripts&lt;/li&gt;
&lt;li&gt;Dynamically imported modules&lt;/li&gt;
&lt;li&gt;Code-split chunks&lt;/li&gt;
&lt;li&gt;Lazy-loaded bundles&lt;/li&gt;
&lt;li&gt;Next.js/React/Vue bundle formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This catches credentials hidden in complex frontend builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Email Verification
&lt;/h3&gt;

&lt;p&gt;When testing requires a verified account, Supabomb integrates with temporary email services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb signup &lt;span class="nt"&gt;--verify-email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✓ Email verification required - using temporary email service
Created temporary email: xyz123@mail.tm

Registering user...
⏳ Account created, waiting &lt;span class="k"&gt;for &lt;/span&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates a temporary email address&lt;/li&gt;
&lt;li&gt;Registers with your Supabase project&lt;/li&gt;
&lt;li&gt;Waits for the verification email&lt;/li&gt;
&lt;li&gt;Clicks the verification link&lt;/li&gt;
&lt;li&gt;Caches the authenticated session&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No manual intervention needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Side-by-Side Access Comparison
&lt;/h3&gt;

&lt;p&gt;Instantly see what's exposed to anonymous vs. authenticated users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;┌────────────────┬───────────┬───────────────┐
│ 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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edge Function Discovery
&lt;/h3&gt;

&lt;p&gt;Unique to Supabomb: it extracts edge function invocations directly from JavaScript code and tests them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run supabomb check-jwt &lt;span class="nt"&gt;-e&lt;/span&gt; send_email &lt;span class="nt"&gt;-e&lt;/span&gt; get_posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;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          │
└─────────────────────────┴──────────────────┴──────────────────────────┴──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals which edge functions require JWT authentication and which are publicly accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Supabomb requires Python 3.13+ and uses &lt;code&gt;uv&lt;/code&gt; for dependency management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/Victoratus/supabomb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;supabomb

&lt;span class="c"&gt;# Run with uv (handles dependencies automatically)&lt;/span&gt;
uv run supabomb &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For deep crawling features, install Katana:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/projectdiscovery/katana/cmd/katana@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example Workflow
&lt;/h2&gt;

&lt;p&gt;Here's a typical security assessment workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Discover credentials from the target application&lt;/span&gt;
uv run supabomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://target-app.com &lt;span class="nt"&gt;--katana&lt;/span&gt;

&lt;span class="c"&gt;# 2. See what resources are accessible (anonymous)&lt;/span&gt;
uv run supabomb enum

&lt;span class="c"&gt;# 3. Run security tests&lt;/span&gt;
uv run supabomb &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# 4. If issues found, test write permissions&lt;/span&gt;
uv run supabomb test-write

&lt;span class="c"&gt;# 5. Register for authenticated testing&lt;/span&gt;
uv run supabomb signup &lt;span class="nt"&gt;--verify-email&lt;/span&gt;

&lt;span class="c"&gt;# 6. Re-run tests with authenticated session (automatic)&lt;/span&gt;
uv run supabomb enum
uv run supabomb &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# 7. Export evidence&lt;/span&gt;
uv run supabomb dump &lt;span class="nt"&gt;-o&lt;/span&gt; ./evidence/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Responsible Use
&lt;/h2&gt;

&lt;p&gt;Supabomb is designed for &lt;strong&gt;authorized security assessments only&lt;/strong&gt;. Always ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Written authorization from the application owner&lt;/li&gt;
&lt;li&gt;Permission to test the specific Supabase project&lt;/li&gt;
&lt;li&gt;Understanding of applicable laws in your jurisdiction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never use this tool against applications you don't own or have explicit permission to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Powers ModernPentest
&lt;/h2&gt;

&lt;p&gt;Supabomb is the foundation of our &lt;a href="//modernpentest.com/supabase-security"&gt;Supabase security scanning&lt;/a&gt; at ModernPentest. Our AI agents use Supabomb as their primary tool for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated RLS policy analysis&lt;/li&gt;
&lt;li&gt;Storage bucket permission auditing&lt;/li&gt;
&lt;li&gt;PostgREST API security testing&lt;/li&gt;
&lt;li&gt;Continuous monitoring for configuration drift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference? ModernPentest adds:&lt;/p&gt;

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

&lt;p&gt;If you want manual control, use Supabomb directly. If you want automated, continuous security with compliance reporting, &lt;a href="//modernpentest.com/supabase-security"&gt;try ModernPentest&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;The code is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Victoratus/supabomb" rel="noopener noreferrer"&gt;github.com/Victoratus/supabomb&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;For comprehensive coverage of common Supabase security issues, check out our guide: &lt;a href="//modernpentest.com/blog/supabase-security-misconfigurations"&gt;10 Common Supabase Security Misconfigurations&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Supabomb is part of our commitment to open source security tooling. Follow us for more tools and guides on securing modern web applications.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>security</category>
      <category>opensource</category>
      <category>cli</category>
    </item>
    <item>
      <title>10 Common Supabase Security Misconfigurations (and How to Fix Them)</title>
      <dc:creator>Victor Yrazusta Ibarra</dc:creator>
      <pubDate>Mon, 08 Dec 2025 19:14:41 +0000</pubDate>
      <link>https://forem.com/victor_yrazusta/10-common-supabase-security-misconfigurations-and-how-to-fix-them-do8</link>
      <guid>https://forem.com/victor_yrazusta/10-common-supabase-security-misconfigurations-and-how-to-fix-them-do8</guid>
      <description>&lt;p&gt;Supabase has become one of the most popular backend-as-a-service platforms for modern web applications. Its PostgreSQL foundation, real-time capabilities, and developer-friendly APIs make it an excellent choice for startups and established companies alike.&lt;/p&gt;

&lt;p&gt;However, with great power comes great responsibility. Supabase's flexibility means there are many ways to misconfigure your security settings, potentially exposing sensitive user data. In this guide, we'll cover the 10 most common Supabase security misconfigurations we've seen in production applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Missing Row-Level Security (RLS)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Critical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most dangerous misconfiguration is having no Row-Level Security (RLS) enabled at all. When RLS is disabled, anyone with your Supabase URL and anon key (which is public) can read, update, or delete all data in your tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- This table has NO RLS - anyone can access all data&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;references&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;full_name&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;credit_card_last_four&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Always enable RLS and create appropriate policies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Enable RLS&lt;/span&gt;
&lt;span class="k"&gt;alter&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt; &lt;span class="k"&gt;security&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Allow users to read only their own profile&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can read own profile"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Allow users to update only their own profile&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can update own profile"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;update&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Overly Permissive RLS Policies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: High&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even with RLS enabled, policies that are too broad can expose data. A common mistake is using &lt;code&gt;true&lt;/code&gt; or weak conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- This policy allows ANY authenticated user to read ALL profiles&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Authenticated users can read profiles"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'authenticated'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Be specific about what data each user can access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Only allow reading your own profile OR public profiles&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Users can read own or public profiles"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
    &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;is_public&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Service Role Key Exposure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Critical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;service_role&lt;/code&gt; key bypasses all RLS policies and should NEVER be exposed to the client. We've seen this key hardcoded in frontend applications, environment variables leaked in client bundles, and even committed to public repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NEVER do this - service_role key in frontend code&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY&lt;/span&gt; &lt;span class="c1"&gt;// DANGER!&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Only use the &lt;code&gt;anon&lt;/code&gt; key in client-side code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Correct - using anon key which respects RLS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_ANON_KEY&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep &lt;code&gt;service_role&lt;/code&gt; key only in server-side code (API routes, server actions, edge functions).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Insecure Storage Bucket Policies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: High&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supabase Storage uses similar RLS-style policies, but many developers forget to configure them, leaving files publicly accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Default policy allows public access to all files&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Public access"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="k"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'avatars'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Restrict access based on ownership:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Users can only access their own files&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"User can access own files"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="k"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bucket_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'user-files'&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foldername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Users can upload to their own folder&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"User can upload own files"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="k"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;insert&lt;/span&gt;
  &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bucket_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'user-files'&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foldername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Missing Email Verification
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Medium&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, Supabase allows users to sign up and immediately access the application without verifying their email. This enables account enumeration and fake account creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User can sign up and immediately access protected resources&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// data.user exists and can be used immediately&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Enable email confirmation in Supabase Dashboard under Authentication &amp;gt; Settings&lt;/li&gt;
&lt;li&gt;Check email confirmation status in your RLS policies:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="nv"&gt;"Only verified users can access data"&lt;/span&gt;
  &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;sensitive_data&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'email_confirmed_at'&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Direct Table Access via PostgREST
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Medium&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supabase exposes your database through PostgREST, which means any table can be queried directly if not properly secured. Developers sometimes create tables without RLS, thinking they're "internal only."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Anyone can query this table directly via the REST API&lt;/span&gt;
curl &lt;span class="s1"&gt;'https://your-project.supabase.co/rest/v1/internal_logs'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"apikey: YOUR_ANON_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Always enable RLS on all tables, even "internal" ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Secure internal tables by denying all access via RLS&lt;/span&gt;
&lt;span class="k"&gt;alter&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;internal_logs&lt;/span&gt; &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="k"&gt;level&lt;/span&gt; &lt;span class="k"&gt;security&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- No policies = no access via PostgREST&lt;/span&gt;
&lt;span class="c1"&gt;-- Access only through server-side code with service_role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Exposed Database Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: High&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL functions created with &lt;code&gt;SECURITY DEFINER&lt;/code&gt; run with the privileges of the function creator, not the calling user. If exposed via PostgREST without proper checks, they can bypass RLS.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- This function runs with elevated privileges&lt;/span&gt;
&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;replace&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;delete_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt;
&lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="k"&gt;sql&lt;/span&gt;
&lt;span class="k"&gt;security&lt;/span&gt; &lt;span class="k"&gt;definer&lt;/span&gt;
&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Add authorization checks inside the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;replace&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;delete_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt;
&lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt;
&lt;span class="k"&gt;security&lt;/span&gt; &lt;span class="k"&gt;definer&lt;/span&gt;
&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;begin&lt;/span&gt;
  &lt;span class="c1"&gt;-- Check if the calling user is authorized&lt;/span&gt;
  &lt;span class="n"&gt;if&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;target_id&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="s1"&gt;'Not authorized'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;if&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;user_profiles&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Weak Password Requirements
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Medium&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supabase's default minimum password length is 6 characters, which is quite weak by modern standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Configure stronger password requirements in your Supabase Dashboard under Authentication &amp;gt; Settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimum length: 12 characters&lt;/li&gt;
&lt;li&gt;Require uppercase, lowercase, numbers, and symbols&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, implement client-side validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;passwordSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password must be at least 12 characters&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password must contain uppercase letter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password must contain lowercase letter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password must contain a number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;A-Za-z0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password must contain special character&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Missing Rate Limiting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: Medium&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supabase doesn't have built-in rate limiting for authentication endpoints, making your app vulnerable to brute force attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Implement rate limiting at the application level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Using Upstash Redis for rate limiting&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Ratelimit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@upstash/ratelimit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@upstash/redis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ratelimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Ratelimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEnv&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ratelimit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slidingWindow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1 m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 5 attempts per minute&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;signIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;success&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ratelimit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too many login attempts. Please try again later.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInWithPassword&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Misconfigured Edge Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Severity: High&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Supabase Edge Functions are powerful serverless functions that run on Deno. A common mistake is deploying functions without proper JWT verification, making them accessible to anyone who knows the endpoint URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This edge function has NO authentication check&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/std@0.168.0/http/server.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// DANGER: Anyone can call this endpoint!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Performing privileged operations without auth&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;adminClient&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Always verify the JWT token and extract the user from it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/std@0.168.0/http/server.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://esm.sh/@supabase/supabase-js@2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Extract the JWT from the Authorization header&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;authHeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Missing authorization header&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Create a Supabase client with the user's JWT&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPABASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPABASE_ANON_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authHeader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Verify the token and get the user&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Now safely use user.id instead of trusting client input&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Detecting These Issues Automatically
&lt;/h2&gt;

&lt;p&gt;Manually checking all tables, policies, and configurations is tedious and error-prone. We built &lt;strong&gt;&lt;a href="https://github.com/Victoratus/supabomb" rel="noopener noreferrer"&gt;Supabomb&lt;/a&gt;&lt;/strong&gt;, an open source CLI tool specifically for Supabase security testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install and run&lt;/span&gt;
git clone https://github.com/Victoratus/supabomb.git
&lt;span class="nb"&gt;cd &lt;/span&gt;supabomb

&lt;span class="c"&gt;# Discover credentials from your app&lt;/span&gt;
uv run supabomb discover &lt;span class="nt"&gt;--url&lt;/span&gt; https://your-app.com

&lt;span class="c"&gt;# Run security tests&lt;/span&gt;
uv run supabomb &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supabomb automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discovers Supabase credentials from your frontend&lt;/li&gt;
&lt;li&gt;Enumerates all accessible tables and storage buckets&lt;/li&gt;
&lt;li&gt;Tests RLS policies and identifies misconfigurations&lt;/li&gt;
&lt;li&gt;Compares anonymous vs. authenticated access&lt;/li&gt;
&lt;li&gt;Generates detailed findings reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about it in our &lt;a href="//modernpentest.com/blog/introducing-supabomb"&gt;Introducing Supabomb&lt;/a&gt; post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Securing your Supabase application requires a defense-in-depth approach. Here's a checklist to review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] RLS is enabled on ALL tables&lt;/li&gt;
&lt;li&gt;[ ] RLS policies are specific and well-tested&lt;/li&gt;
&lt;li&gt;[ ] Service role key is only used server-side&lt;/li&gt;
&lt;li&gt;[ ] Storage bucket policies are configured&lt;/li&gt;
&lt;li&gt;[ ] Email verification is required&lt;/li&gt;
&lt;li&gt;[ ] All database functions have proper authorization checks&lt;/li&gt;
&lt;li&gt;[ ] Password requirements are strong&lt;/li&gt;
&lt;li&gt;[ ] Rate limiting is implemented&lt;/li&gt;
&lt;li&gt;[ ] Edge Functions verify JWT tokens before processing requests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automate Your Supabase Security
&lt;/h2&gt;

&lt;p&gt;Want continuous protection instead of manual checks? &lt;strong&gt;&lt;a href="//modernpentest.com/supabase-security"&gt;ModernPentest's Supabase Security Scanning&lt;/a&gt;&lt;/strong&gt; uses AI agents trained specifically on Supabase vulnerabilities to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scan in under an hour&lt;/strong&gt; - Full penetration test + SOC 2 report&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catch RLS bypasses&lt;/strong&gt; - The same issues covered in this guide, detected automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor continuously&lt;/strong&gt; - Weekly/daily scans catch regressions before attackers do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate compliance reports&lt;/strong&gt; - Auditor-ready documentation for SOC 2, ISO 27001&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our agents use Supabomb under the hood, combined with AI analysis to prioritize findings by actual risk and provide specific remediation guidance.&lt;/p&gt;

&lt;p&gt;&lt;a href="//modernpentest.com/supabase-security"&gt;&lt;strong&gt;Start Your Free Security Scan →&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This guide is part of our Security Guides series. Follow us for more content on securing modern web applications.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>security</category>
      <category>postgres</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
