en un clic
db-rls-audit
Report tables with/without RLS and list all policies
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
Report tables with/without RLS and list all policies
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Basé sur la classification professionnelle SOC
Execute story development with selectable automation modes to accommodate different developer preferences, skill levels, and story complexity.
Set up a Kord-aligned documentation baseline (no legacy frameworks)
Create Next Story Task methodology and workflow
Validate Next Story Task methodology and workflow
advanced-elicitation methodology and workflow
No checklists needed - this task facilitates brainstorming sessions, validation is through user interaction methodology and workflow
| name | db-rls-audit |
| description | Report tables with/without RLS and list all policies |
| agent | architect |
| subtask | false |
Report tables with/without RLS and list all policies
Parameter:* mode (optional, default: interactive)
Purpose:* Definitive pass/fail criteria for task completion
Checklist:*
acceptance-criteria:
- [ ] Data persisted correctly; constraints respected; no orphaned data
type: acceptance-criterion
blocker: true
validation: |
Assert data persisted correctly; constraints respected; no orphaned data
error_message: "Acceptance criterion not met: Data persisted correctly; constraints respected; no orphaned data"
Strategy:* retry
Common Errors:*
Error:* Connection Failed
Error:* Query Syntax Error
Error:* Transaction Rollback
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 <<'SQL'
\echo '=== RLS Coverage Audit ==='
\echo ''
-- Tables with/without RLS
WITH t AS (
SELECT tablename, rowsecurity
FROM pg_tables WHERE schemaname='public'
)
SELECT
tablename,
CASE WHEN rowsecurity THEN '✓ ENABLED' ELSE '❌ DISABLED' END AS rls_status,
(SELECT json_agg(json_build_object(
'policy', policyname,
'cmd', cmd,
'roles', roles,
'qual', qual,
'with_check', with_check
))
FROM pg_policies p
WHERE p.tablename=t.tablename
AND p.schemaname='public') AS policies
FROM t
ORDER BY rowsecurity DESC, tablename;
\echo ''
\echo '=== Summary ==='
SELECT
COUNT(*) AS total_tables,
COUNT(*) FILTER (WHERE rowsecurity) AS rls_enabled,
COUNT(*) FILTER (WHERE NOT rowsecurity) AS rls_disabled
FROM pg_tables
WHERE schemaname='public';
\echo ''
\echo '=== Tables Without RLS (Security Risk) ==='
SELECT tablename
FROM pg_tables
WHERE schemaname='public'
AND rowsecurity = false
ORDER BY tablename;
\echo ''
\echo '=== Policy Coverage ==='
SELECT
t.tablename,
COUNT(p.policyname) AS policy_count,
ARRAY_AGG(p.cmd) AS commands_covered
FROM pg_tables t
LEFT JOIN pg_policies p ON p.tablename = t.tablename AND p.schemaname = 'public'
WHERE t.schemaname = 'public'
AND t.rowsecurity = true
GROUP BY t.tablename
ORDER BY policy_count, t.tablename;
SQL
✓ ENABLED - Table has RLS active (good)
❌ DISABLED - Table has no RLS (security risk)
Good coverage:*
FOR ALL (KISS approach), ORIncomplete coverage:*
No coverage:*
Problem*: RLS enabled but no policies defined
Impact*: Table is inaccessible to all users
Fix*: Add policies or disable RLS
-- Add KISS policy
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
CREATE POLICY "table_name_all"
ON table_name FOR ALL
TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
Or use: policy-apply table_name kiss
Problem*: Table accessible without restrictions
Impact*: Security vulnerability, data exposure
Fix*: Enable RLS and add policies
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
-- Then add policies
Problem*: RLS enabled with 1-3 policies (not covering all operations)
Impact*: Some operations may be blocked unexpectedly
Fix*: Either add missing policies or switch to KISS approach
Tables that should be publicly readable:
-- Public read, authenticated write
CREATE POLICY "public_read"
ON table_name FOR SELECT
TO anon, authenticated
USING (true);
CREATE POLICY "authenticated_write"
ON table_name FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
Use KISS policy:
policy-apply table_name kiss
Organization-scoped access:
CREATE POLICY "org_isolation"
ON table_name FOR ALL
TO authenticated
USING (org_id = (auth.jwt() ->> 'org_id')::uuid)
WITH CHECK (org_id = (auth.jwt() ->> 'org_id')::uuid);
After fixing issues, test with:
impersonate {user_id}
# Then run queries to verify access
✅ Enable RLS on all tables with sensitive data*
✅ Use KISS policies for simple owner-based access*
✅ Document why RLS is disabled if intentional*
✅ Test policies with real user contexts*
✅ Index columns used in RLS policies*
✅ Run this audit after every migration*
❌ Don't enable RLS without policies*
❌ Don't use service role to bypass RLS in app code*
❌ Don't forget to test negative cases*
Run RLS audit:
smoke-test → rls-auditrls-auditrls-auditrls-audit