# Rls Audit

> Authorized defensive security audit of a Supabase project you own — anon-key exposure, RLS gaps, service-role logging. Use for "what's exposed with the anon key", "rls audit", "security audit the backend".

- Skill: `danielimad/rls-audit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add danielimad/rls-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/danielimad/rls-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: danielimad (https://skillmd.com/u/danielimad)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/danielimad/rls-audit

---


# RLS Audit — authorized self-audit

**Precondition: the user owns the project being audited.** This is defensive security against your own infrastructure — confirm the project ref belongs to the user before starting. Do not run this against a third party's project.

Parity partner: /rls-enforce. This skill finds and reports; that one closes the gaps.

## Sweep
1. **Enumerate the anon surface**: every table, view, RPC, storage bucket, and edge function reachable with the public anon key (REST catalog + storage list + functions list).
2. **Test as anon**: read/insert/update/delete attempts against each surface — read-only where possible; any write test uses throwaway rows that are rolled back/deleted immediately.
3. **Test as a self-registered user**: sign up a scratch account, repeat the sweep — cross-tenant reads are the killer (can user A see workspace B's rows?).
4. **Edge functions**: which are world-callable? Do they verify JWT + ownership INSIDE the function? This matters most when functions are deployed with `--no-verify-jwt`, which moves auth from the platform into your code. Check for module-level caches that can bleed across tenants on warm instances — a per-tenant value cached at module scope gets served to whoever hits that instance next.
5. **Service-role hygiene**: service-role actions must be logged with full detail; flag unlogged service-role paths and missing audit tables.

## Output — the findings (the handoff to /rls-enforce)
This skill FINDS; it does not fix. Produce a dated findings doc in the repo's docs security folder (`.docs/security/` by default, or whatever the repo's runbook/convention names as its docs folder) and a structured findings list that /rls-enforce consumes directly. Each finding:
- `surface` — table / view / RPC / bucket / edge function.
- `table_class` — owner-scoped | reference/config | server-internal | public-catalog (best inference; /rls-enforce confirms).
- `gap` — the specific hole: RLS-off · permissive `USING(true)` write · PII/cost column client-readable · world-callable definer fn · cross-tenant read · missing WITH CHECK · unlogged service-role path.
- `severity` — Critical/High/Medium/Low, ranked worst-first.
- `reproduction` — exact request + what came back. Receipts, not theory.
Then hand off: "run /rls-enforce to close these" — remediation, migrations, and re-verify live there. Do NOT write fix migrations in this skill.

## Rules
- Read-only exposure audit: production data untouched except the throwaway scratch rows described above; no deletes of real rows, no load/stress tests.
- Parity: the findings shape above is the exact input /rls-enforce expects — audit finds, enforce closes, both re-test with the same sweep.

