
Supabase Audit Rls
- 662 installs
- 60 repo stars
- Updated January 31, 2026
- yoanbernabeu/supabase-pentest-skills
supabase-audit-rls is a Claude Code pentest skill that progressively tests Supabase Row Level Security policies for bypass vulnerabilities and writes findings to .sb-pentest-context.json and .sb-pentest-audit.log.
About
supabase-audit-rls from yoanbernabeu/supabase-pentest-skills audits Supabase Row Level Security before production deploys. It exercises policies for common bypass paths and misconfigurations, mandating progressive file updates: each finding lands immediately in .sb-pentest-context.json while .sb-pentest-audit.log records activity before and after every test so interrupted runs retain evidence. Developers reach for supabase-audit-rls when Postgres RLS is enabled but untested, or when agents need a repeatable security checklist instead of manual SQL spot checks. Failure to write findings progressively is treated as a critical skill error, reflecting the high stakes of silent data exposure.
- Scans all RLS policies for common misconfigurations and bypass risks
- Flags overly permissive SELECT, INSERT, UPDATE, and DELETE rules
- Checks for missing authentication context and insecure function usage
- Produces a severity-ranked report with remediation steps
- Designed specifically for Supabase Postgres security model
Supabase Audit Rls by the numbers
- 662 all-time installs (skills.sh)
- +21 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #461 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-rlsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 662 |
|---|---|
| repo stars | ★ 60 |
| Last updated | January 31, 2026 |
| Repository | yoanbernabeu/supabase-pentest-skills ↗ |
How do you audit Supabase RLS policies for bypasses?
Automatically audit Supabase Row Level Security policies before deploying a production backend.
Who is it for?
Backend developers shipping Supabase Postgres with RLS who need automated bypass testing before production deployment.
Skip if: Projects without Supabase or Postgres RLS, or teams wanting general OWASP web scans instead of database policy audits.
When should I use this skill?
The user deploys Supabase with Row Level Security, mentions RLS policy testing, or references supabase pentest audit workflows.
What you get
.sb-pentest-context.json findings file, .sb-pentest-audit.log test log, and documented RLS vulnerability report.
- .sb-pentest-context.json findings
- .sb-pentest-audit.log
- RLS vulnerability assessment
Files
RLS Policy Audit
🔴 CRITICAL: PROGRESSIVE FILE UPDATES REQUIRED
>
You MUST write to context files AS YOU GO, not just at the end.
- Write to .sb-pentest-context.json IMMEDIATELY after each finding- Log to .sb-pentest-audit.log BEFORE and AFTER each test- DO NOT wait until the skill completes to update files
- If the skill crashes or is interrupted, all prior findings must already be saved
>
This is not optional. Failure to write progressively is a critical error.
This skill tests Row Level Security (RLS) policies for common vulnerabilities and misconfigurations.
When to Use This Skill
- After discovering data exposure in tables
- To verify RLS policies are correctly implemented
- To test for common RLS bypass techniques
- As part of a comprehensive security audit
Prerequisites
- Tables listed
- Anon key available
- Preferably also test with an authenticated user token
Understanding RLS
Row Level Security in Supabase/PostgreSQL:
-- Enable RLS on a table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- Create a policy
CREATE POLICY "Users see own posts"
ON posts FOR SELECT
USING (auth.uid() = author_id);If RLS is enabled but no policies exist, ALL access is blocked.
Common RLS Issues
| Issue | Description | Severity |
|---|---|---|
| RLS Disabled | Table has no RLS protection | P0 |
| Missing Policy | RLS enabled but no SELECT policy | Variable |
| Overly Permissive | Policy allows too much access | P0-P1 |
| Missing Operation | SELECT policy but no INSERT/UPDATE/DELETE | P1 |
| USING vs WITH CHECK | Read allowed but write inconsistent | P1 |
Test Vectors
The skill tests these common bypass scenarios:
1. Unauthenticated Access
GET /rest/v1/users?select=*
# No Authorization header or with anon key only2. Cross-User Access
# As user A, try to access user B's data
GET /rest/v1/orders?user_id=eq.[user-b-id]
Authorization: Bearer [user-a-token]3. Filter Bypass
# Try to bypass filters with OR conditions
GET /rest/v1/posts?or=(published.eq.true,published.eq.false)4. Join Exploitation
# Try to access data through related tables
GET /rest/v1/comments?select=*,posts(*)5. RPC Bypass
# Check if RPC functions bypass RLS
POST /rest/v1/rpc/get_all_usersUsage
Basic RLS Audit
Audit RLS policies on my Supabase projectSpecific Table
Test RLS on the users tableWith Authenticated User
Test RLS policies using this user token: eyJ...Output Format
═══════════════════════════════════════════════════════════
RLS POLICY AUDIT
═══════════════════════════════════════════════════════════
Project: abc123def.supabase.co
Tables Audited: 8
─────────────────────────────────────────────────────────
RLS Status by Table
─────────────────────────────────────────────────────────
1. users
RLS Enabled: ❌ NO
Status: 🔴 P0 - NO RLS PROTECTION
All operations allowed without restriction!
Test Results:
├── Anon SELECT: ✓ Returns all 1,247 rows
├── Anon INSERT: ✓ Succeeds (tested with rollback)
├── Anon UPDATE: ✓ Would succeed
└── Anon DELETE: ✓ Would succeed
Immediate Fix:ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users see own data" ON users FOR ALL USING (auth.uid() = id);
2. posts
RLS Enabled: ✅ YES
Policies Found: 2
Status: ✅ PROPERLY CONFIGURED
Policies:
├── "Public sees published" (SELECT)
│ └── USING: (published = true)
└── "Authors manage own" (ALL)
└── USING: (auth.uid() = author_id)
Test Results:
├── Anon SELECT: Only published posts (correct)
├── Anon INSERT: ❌ Blocked (correct)
├── Cross-user access: ❌ Blocked (correct)
└── Filter bypass: ❌ Blocked (correct)
3. orders
RLS Enabled: ✅ YES
Policies Found: 1
Status: 🟠 P1 - PARTIAL ISSUE
Policies:
└── "Users see own orders" (SELECT)
└── USING: (auth.uid() = user_id)
Issue Found:
├── No INSERT policy - users can't create orders via API
├── No UPDATE policy - users can't modify their orders
└── This may be intentional (orders via Edge Functions)
Recommendation: Document if intentional, or add policies:CREATE POLICY "Users insert own orders" ON orders FOR INSERT WITH CHECK (auth.uid() = user_id);
4. comments
RLS Enabled: ✅ YES
Policies Found: 2
Status: 🟠 P1 - BYPASS POSSIBLE
Policies:
├── "Anyone can read" (SELECT)
│ └── USING: (true) ← Too permissive
└── "Users comment on posts" (INSERT)
└── WITH CHECK: (auth.uid() = user_id)
Issue Found:
└── SELECT policy allows reading all comments
including user_id, enabling user correlation
Recommendation:-- Use a view to hide user_id CREATE VIEW public.comments_public AS SELECT id, post_id, content, created_at FROM comments;
5. settings
RLS Enabled: ❌ NO
Status: 🔴 P0 - NO RLS PROTECTION
Contains sensitive configuration!
Immediate action required.
─────────────────────────────────────────────────────────
Summary
─────────────────────────────────────────────────────────
RLS Disabled: 2 tables (users, settings) ← CRITICAL
RLS Enabled: 6 tables
├── Properly Configured: 3
├── Partial Issues: 2
└── Major Issues: 1
Bypass Tests:
├── Unauthenticated access: 2 tables vulnerable
├── Cross-user access: 0 tables vulnerable
├── Filter bypass: 0 tables vulnerable
└── Join exploitation: 1 table allows data leakage
═══════════════════════════════════════════════════════════Context Output
{
"rls_audit": {
"timestamp": "2025-01-31T10:45:00Z",
"tables_audited": 8,
"summary": {
"rls_disabled": 2,
"rls_enabled": 6,
"properly_configured": 3,
"partial_issues": 2,
"major_issues": 1
},
"findings": [
{
"table": "users",
"rls_enabled": false,
"severity": "P0",
"issue": "No RLS protection",
"operations_exposed": ["SELECT", "INSERT", "UPDATE", "DELETE"]
},
{
"table": "comments",
"rls_enabled": true,
"severity": "P1",
"issue": "Overly permissive SELECT policy",
"detail": "user_id exposed enabling correlation"
}
]
}
}Common RLS Patterns
Good: User owns their data
CREATE POLICY "Users own their data"
ON user_data FOR ALL
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);Good: Public read, authenticated write
-- Anyone can read
CREATE POLICY "Public read" ON posts
FOR SELECT USING (published = true);
-- Only authors can write
CREATE POLICY "Author write" ON posts
FOR INSERT WITH CHECK (auth.uid() = author_id);
CREATE POLICY "Author update" ON posts
FOR UPDATE USING (auth.uid() = author_id);Bad: Using (true)
-- ❌ Too permissive
CREATE POLICY "Anyone" ON secrets
FOR SELECT USING (true);Bad: Forgetting WITH CHECK
-- ❌ Users can INSERT any user_id
CREATE POLICY "Insert" ON posts
FOR INSERT WITH CHECK (true); -- Should check user_id!RLS Bypass Documentation
For each bypass found, the skill provides:
1. Description of the vulnerability 2. Proof of concept query 3. Impact assessment 4. Fix with SQL code 5. Documentation link
MANDATORY: Progressive Context File Updates
⚠️ This skill MUST update tracking files PROGRESSIVELY during execution, NOT just at the end.
Critical Rule: Write As You Go
DO NOT batch all writes at the end. Instead:
1. Before testing each table → Log the action to .sb-pentest-audit.log 2. After each RLS finding → Immediately update .sb-pentest-context.json 3. After each test completes → Log the result to .sb-pentest-audit.log
This ensures that if the skill is interrupted, crashes, or times out, all findings up to that point are preserved.
Required Actions (Progressive)
1. Update `.sb-pentest-context.json` with results:
{
"rls_audit": {
"timestamp": "...",
"tables_audited": 8,
"summary": { "rls_disabled": 2, ... },
"findings": [ ... ]
}
}2. Log to `.sb-pentest-audit.log`:
[TIMESTAMP] [supabase-audit-rls] [START] Auditing RLS policies
[TIMESTAMP] [supabase-audit-rls] [FINDING] P0: users table has no RLS
[TIMESTAMP] [supabase-audit-rls] [CONTEXT_UPDATED] .sb-pentest-context.json updated3. If files don't exist, create them before writing.
FAILURE TO UPDATE CONTEXT FILES IS NOT ACCEPTABLE.
MANDATORY: Evidence Collection
📁 Evidence Directory: .sb-pentest-evidence/03-api-audit/rls-tests/
Evidence Files to Create
| File | Content |
|---|---|
rls-tests/[table]-anon.json | Anonymous access test results |
rls-tests/[table]-auth.json | Authenticated access test results |
rls-tests/cross-user-test.json | Cross-user access attempts |
Evidence Format (RLS Bypass)
{
"evidence_id": "RLS-001",
"timestamp": "2025-01-31T10:25:00Z",
"category": "api-audit",
"type": "rls_test",
"severity": "P0",
"table": "users",
"rls_enabled": false,
"tests": [
{
"test_name": "anon_select",
"description": "Anonymous user SELECT access",
"request": {
"curl_command": "curl -s '$URL/rest/v1/users?select=*&limit=5' -H 'apikey: $ANON_KEY'"
},
"response": {
"status": 200,
"rows_returned": 5,
"total_accessible": 1247
},
"result": "VULNERABLE",
"impact": "All user data accessible without authentication"
},
{
"test_name": "anon_insert",
"description": "Anonymous user INSERT access",
"request": {
"curl_command": "curl -X POST '$URL/rest/v1/users' -H 'apikey: $ANON_KEY' -d '{...}'"
},
"response": {
"status": 201
},
"result": "VULNERABLE",
"impact": "Can create arbitrary user records"
}
],
"remediation_sql": "ALTER TABLE users ENABLE ROW LEVEL SECURITY;\nCREATE POLICY \"Users see own data\" ON users FOR SELECT USING (auth.uid() = id);"
}Add to curl-commands.sh
# === RLS BYPASS TESTS ===
# Test anon access to users table
curl -s "$SUPABASE_URL/rest/v1/users?select=*&limit=5" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY"
# Test filter bypass
curl -s "$SUPABASE_URL/rest/v1/posts?or=(published.eq.true,published.eq.false)" \
-H "apikey: $ANON_KEY"Related Skills
supabase-audit-tables-list— List tables firstsupabase-audit-tables-read— See actual data exposuresupabase-audit-rpc— RPC functions can bypass RLSsupabase-report— Full security report
Related skills
FAQ
What files does supabase-audit-rls update?
supabase-audit-rls writes each finding immediately to .sb-pentest-context.json and logs test activity to .sb-pentest-audit.log before and after every check so partial runs still preserve audit evidence.
Why is progressive logging required?
supabase-audit-rls treats progressive updates as mandatory because crashes or interruptions must not lose prior RLS findings; skipping incremental writes is documented as a critical skill failure.