| name | security-hardening |
| description | Use when auditing RLS policies, hardening auth sessions, adding CSP headers, rotating secrets, or before shipping any feature to production. Triggers on "security", "RLS audit", "auth hardening", "CSP", "secrets", "ship to production". |
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 in App.tsx
- Check
useAuth handles expired sessions (redirect to login)
- Verify OAuth callback doesn't leak tokens in URL params
- Confirm no session data in
console.log or error messages
Phase 3: Environment & Secrets
- Scan:
grep -r "sk-\|sk_live\|SUPABASE_SERVICE" src/
- Verify
.env in .gitignore
- Only
VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY exposed to client
- Edge functions use
Deno.env.get(), never hardcoded
- No secrets in git history
Phase 4: Security Headers
Content-Security-Policy configured
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
429 with Retry-After header
Checklist
References
.claude/supabase/references/RLS-POLICIES.md
.claude/edge-functions/references/SECURITY.md
plan/audit/ — Previous audit reports