Seis políticas RLS de Supabase que pasan la revisión y filtran datos
Un repaso a los errores más comunes en Row Level Security deja claro que la política peligrosa no es la que se ve mal, sino la que pasa la revisión y deja las filas expuestas.

La anon key de Supabase viaja dentro del bundle de la aplicación y cualquiera puede extraerla. Lo único que queda entre ese desconocido y tu tabla de pedidos es la política que alguien escribió en SQL a las once de la noche. Un repaso a los seis fallos más repetidos en Row Level Security concluye algo incómodo: los peligrosos no son los que se ven mal y se corrigen en revisión, sino los que se leen bien y filtran datos solo cuando alguien lo intenta.
Los que se cuelan en la revisión
La tabla sin RLS activado es el primero. No hay política mala, simplemente no hay ninguna, porque nadie habilitó la seguridad en esa tabla creada por una migración a mano o generada por una IA. El resultado es una tabla pública: la lee y la escribe cualquiera con la anon key. El arreglo es estructural, no disciplinario: una función que liste las tablas del esquema public sin relrowsecurity y un test que se ejecute en cada migración. Es la comprobación que más fugas reales detecta de las seis.
El segundo es un update con using pero sin with check. using decide qué filas existentes puede tocar el usuario; with check decide qué aspecto puede tener la fila después de la escritura. Con solo using, un usuario selecciona su propia fila y después cambia su id por el de otro, o reasigna el propietario en una tabla con columna user_id. En insert pasa lo mismo: with check es la única cláusula que impide crear filas a nombre de cualquiera.
El tercero tiene que ver con dónde se guarda la autorización. Poner el rol en raw_user_meta_data es cómodo, porque está en el JWT, y es también el exploit completo: el propio usuario actualiza su metadata desde el cliente, refresca la sesión y ya es administrador. app_metadata solo la escribe el service role, así que es de fiar. Mejor todavía, una tabla de roles con RLS activado y sin políticas, consultada con un exists dentro de la policy.
El cuarto es no poner la cláusula to. Si falta, la política aplica a public, que incluye el rol anon. Para posts publicados puede dar igual, pero al copiar el patrón a notificaciones o a cualquier tabla privada se abre la lectura a quien ni siquiera ha iniciado sesión. Cuando la intención es usuario autenticado, se escribe to authenticated.
Lo que no se ve en el SQL
Las vistas y las funciones security definer se saltan RLS sin avisar, y hay que auditarlas una por una. A eso se suma el rendimiento: auth.uid() sin envolver en (select auth.uid()) se reevalúa fila a fila y las políticas se arrastran a escala.
Todos estos fallos son testeables, y ahí está el punto. Una política sin test es una esperanza, no un control de acceso. El trabajo pendiente para quien tenga Supabase en producción es aburrido y concreto: añadir el test de tablas sin RLS al pipeline, revisar cada update e insert que solo tenga using, sacar los roles del metadata del usuario y repasar vistas y funciones definer.

