This directory contains automated scripts to verify Row Level Security (RLS) policies across all database tables, preventing data leaks as outlined in Issue #14.
The RLS audit system ensures that EVERY table in the public schema has:
- Row Level Security enabled (
ALTER TABLE ... ENABLE ROW LEVEL SECURITY) - At least one active policy defined (
CREATE POLICY ...)
Primary audit script - Node.js implementation for CI/CD integration.
# Run with environment variables
SUPABASE_URL=your_url SUPABASE_SERVICE_ROLE_KEY=your_key node scripts/check-rls-compliance.js
# Or use npm scripts (from backend directory)
npm run audit:rls # Uses env vars
npm run audit:rls:local # Uses local Supabase instanceFeatures:
- ✅ Checks all tables in public schema using pg_policies system table
- ✅ Verifies RLS is enabled via pg_class.relrowsecurity
- ✅ Counts active policies per table from pg_policies
- ✅ Colored console output
- ✅ Detailed compliance report
- ✅ Exit code 1 if any issues found (fails CI)
SQL-only version for direct database execution.
-- Run directly in your database
\i scripts/audit-rls-policies.sqlFeatures:
- ✅ Pure SQL implementation
- ✅ Creates temporary audit function
- ✅ Comprehensive table analysis
- ✅ Raises exception if issues found
Advanced Node.js version with fallback mechanisms.
node scripts/audit-rls-policies.jsFeatures:
- ✅ Multiple audit strategies
- ✅ Automatic fallback methods
- ✅ Detailed error handling
- ✅ Function creation and cleanup
Runs on:
- Push to main/develop branches
- PRs affecting migrations or audit scripts
- Changes to RLS audit workflow
# Triggers RLS audit after migrations
- supabase/migrations/**
- backend/migrations/**
- scripts/check-rls-compliance.jsThe existing database.yml workflow now includes RLS auditing:
- name: Run RLS Policy Audit
run: node scripts/check-rls-compliance.js# Start local Supabase
supabase start
# Apply migrations
supabase db push
# Run RLS audit
cd backend
npm run audit:rls:local| Variable | Description | Required |
|---|---|---|
SUPABASE_URL |
Supabase project URL | ✅ |
SUPABASE_SERVICE_ROLE_KEY |
Service role key for admin access | ✅ |
Local Development:
- URL:
http://localhost:54321 - Service Key:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...(default local key)
🔍 Starting RLS Compliance Check...
📊 Database: https://your-project.supabase.co
📋 RLS Compliance Report:
────────────────────────────────────────────────────────────────────────────────
Table Name RLS Policies Status
────────────────────────────────────────────────────────────────────────────────
audit_logs ✓ 3 OK
idempotency_keys ✓ 2 OK
profiles ✓ 4 OK
subscriptions ✓ 4 OK
teams ✓ 5 OK
user_preferences ✓ 3 OK
📊 Summary:
Total tables: 6
Tables with issues: 0
Compliance rate: 100.0%
✅ RLS COMPLIANCE CHECK PASSED
All tables have RLS enabled with policies
Your database is protected against data leaks! 🔒
🔍 Starting RLS Compliance Check...
📊 Database: https://your-project.supabase.co
📋 RLS Compliance Report:
────────────────────────────────────────────────────────────────────────────────
Table Name RLS Policies Status
────────────────────────────────────────────────────────────────────────────────
audit_logs ✓ 3 OK
new_table ✗ 0 MISSING_RLS
subscriptions ✓ 0 NO_POLICIES
📊 Summary:
Total tables: 3
Tables with issues: 2
Compliance rate: 33.3%
❌ RLS Policy Issues Found:
new_table: RLS is not enabled
subscriptions: RLS enabled but no policies defined
🔧 To fix these issues:
1. Enable RLS: ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
2. Add policies: CREATE POLICY policy_name ON table_name FOR SELECT USING (...);
3. Ensure all CRUD operations have appropriate policies
❌ RLS COMPLIANCE CHECK FAILED
2 table(s) missing RLS policies
-- Enable RLS
ALTER TABLE user_data ENABLE ROW LEVEL SECURITY;
-- Policies for user-owned records
CREATE POLICY "user_data_select_own" ON user_data FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "user_data_insert_own" ON user_data FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "user_data_update_own" ON user_data FOR UPDATE USING (auth.uid() = user_id);
CREATE POLICY "user_data_delete_own" ON user_data FOR DELETE USING (auth.uid() = user_id);-- Enable RLS
ALTER TABLE team_data ENABLE ROW LEVEL SECURITY;
-- Policy for team members
CREATE POLICY "team_data_member_access" ON team_data FOR ALL USING (
EXISTS (
SELECT 1 FROM team_members
WHERE team_members.team_id = team_data.team_id
AND team_members.user_id = auth.uid()
)
);-- Policy with admin override
CREATE POLICY "data_select_own_or_admin" ON sensitive_data FOR SELECT USING (
auth.uid() = user_id OR
auth.jwt() ->> 'is_admin' = 'true'
);# Check environment variables
echo $SUPABASE_URL
echo $SUPABASE_SERVICE_ROLE_KEY
# Test connection
curl -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" \
"$SUPABASE_URL/rest/v1/profiles?select=*&limit=1"# Install required packages
cd backend
npm install @supabase/supabase-js# Reset local instance
supabase stop
supabase start
# Check status
supabase status- Check secrets: Ensure
SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEYare set in GitHub secrets - Verify permissions: Service role key must have admin access
- Check migrations: Ensure all migrations apply successfully before audit
- Never commit service role keys to version control
- Use GitHub secrets for CI/CD
- Rotate keys regularly
- Limit key permissions where possible
- Script only checks public schema tables
- Ignores system tables (
pg_%,sql_%) - Does not validate policy logic (only presence)
The audit verifies policies exist but doesn't validate:
- Policy correctness
- Security effectiveness
- Performance impact
- Business logic compliance
# Add to .git/hooks/pre-commit
#!/bin/bash
cd backend
npm run audit:rls:local || {
echo "❌ RLS audit failed - commit blocked"
exit 1
}When creating new tables:
- ✅ Create table
- ✅ Enable RLS:
ALTER TABLE ... ENABLE ROW LEVEL SECURITY - ✅ Add policies for SELECT, INSERT, UPDATE, DELETE
- ✅ Test policies work correctly
- ✅ Run RLS audit:
npm run audit:rls:local - ✅ Commit migration
- Policy logic validation
- Performance impact analysis
- Integration with schema documentation
- Automated policy generation
- Policy coverage reporting
- Security best practice validation