Security Hardening
Overview
Structured workflow to audit and harden security before any feature ships. Covers RLS policies, auth sessions, environment secrets, CSP headers, and rate limiting.
When to Use
- •Before shipping ANY new table or feature to production
- •After creating or modifying RLS policies
- •When auditing authentication flow
- •When rotating secrets or API keys
- •When adding security headers
Workflow
Phase 1: RLS Audit
- •List all tables:
SELECT tablename FROM pg_tables WHERE schemaname = 'public'; - •Verify RLS enabled:
SELECT relname, relrowsecurity FROM pg_class WHERE relname = '<table>'; - •List policies:
SELECT * FROM pg_policies WHERE tablename = '<table>'; - •Verify every policy uses
auth.uid()for user isolation - •Test: user A cannot read user B's data
- •Test: anonymous users get zero rows on protected tables
Pass: Every public table has RLS with SELECT + INSERT + UPDATE + DELETE policies using auth.uid().
Phase 2: Auth Session Hardening
- •Verify Supabase client has
autoRefreshToken: true - •Confirm
<ProtectedRoute>wraps all authenticated pages inApp.tsx - •Check
useAuthhandles expired sessions (redirect to login) - •Verify OAuth callback doesn't leak tokens in URL params
- •Confirm no session data in
console.logor error messages
Phase 3: Environment & Secrets
- •Scan:
grep -r "sk-\|sk_live\|SUPABASE_SERVICE" src/ - •Verify
.envin.gitignore - •Only
VITE_SUPABASE_URLandVITE_SUPABASE_PUBLISHABLE_KEYexposed to client - •Edge functions use
Deno.env.get(), never hardcoded - •No secrets in git history
Phase 4: Security Headers
- •
Content-Security-Policyconfigured - •
X-Frame-Options: DENY - •
X-Content-Type-Options: nosniff - •
Referrer-Policy: strict-origin-when-cross-origin
Phase 5: Rate Limiting
- •Rate limits on public edge functions
- •Per-IP: 100 req/min API, 10/min auth
- •Return
429withRetry-Afterheader
Checklist
- • All tables have RLS enabled
- • All RLS policies use
auth.uid() - • No cross-user data leakage
- • Sessions auto-refresh, no tokens in URLs
- • Zero hardcoded secrets in source
- •
.envin.gitignore - • Security headers configured
- • Rate limiting on public endpoints
References
- •
.claude/supabase/references/RLS-POLICIES.md - •
.claude/edge-functions/references/SECURITY.md - •
plan/audit/— Previous audit reports