// guía de seguridad
Seguridad para apps hechas con Supabase
Supabase es el backend más popular en apps vibe-coded. Postgres + Auth + Storage + Edge Functions, todo manejado. La gran fortaleza de Supabase es Row Level Security; la gran trampa es olvidarse de habilitarla. Esta guía cubre los patrones que más detectamos en audits a apps con Supabase.
// contexto del stack
Contexto de Supabase
En Supabase, la `anon` key viaja en tu bundle por diseño. La protección de tus datos depende casi exclusivamente de RLS bien configurado. La `service_role` key bypassea RLS y nunca debe llegar al cliente. La evidencia es contundente: según Symbiotic Security, de 1.072 apps vibe-coded con Supabase escaneadas, el 98% tenía al menos un fallo de seguridad y el 16% uno crítico —casi siempre por RLS mal configurado o ausente.
// hallazgos frecuentes
Vulnerabilidades más comunes en Supabase
01 Tablas sin RLS habilitado
El error más común. Sin RLS, cualquier visitante con la anon key (que está en el bundle) puede leer todos los datos.
→ cómo arreglarlo
En el SQL editor: `ALTER TABLE nombre ENABLE ROW LEVEL SECURITY` por cada tabla. Y agregar políticas explícitas o la tabla queda completamente bloqueada.
02 Políticas RLS demasiado permisivas
Activar RLS pero crear políticas como `USING (true)` o `USING (auth.role() = 'authenticated')` es equivalente a no tener RLS. Cualquiera puede signupearse y acceder.
→ cómo arreglarlo
Las políticas deben referenciar el usuario específico: `auth.uid() = user_id`. Para acceso por organización: subselect a una tabla de membership.
03 service_role key expuesta en variables públicas
Algunas configuraciones agregan `SUPABASE_SERVICE_ROLE_KEY` al cliente con prefijo público (VITE_, NEXT_PUBLIC_) confundiéndola con la anon key. La service_role bypassa RLS completo.
→ cómo arreglarlo
service_role solo en variables sin prefijo público. Usar exclusivamente en endpoints backend (Edge Functions, API routes server-side). Si filtraste, rotala desde Project Settings → API.
04 Edge Functions sin validación de inputs
Las Edge Functions de Supabase corren en Deno y manejan request handlers manuales. Sin validación, aceptan cualquier payload.
→ cómo arreglarlo
Validá inputs con Zod (vía CDN: `https://esm.sh/zod`). Para cada Edge Function, el primer paso del handler debe ser `Schema.parse(await req.json())`.
05 Storage buckets sin políticas
Los buckets de Storage también usan RLS via la tabla interna `storage.objects`. Sin políticas explícitas, los archivos pueden quedar public o completamente bloqueados.
→ cómo arreglarlo
En el dashboard de Storage → Policies, configurá políticas para cada bucket. Para archivos privados por usuario: `bucket_id = "X" AND auth.uid()::text = (storage.foldername(name))[1]`.
// checklist pre-launch
Checklist pre-launch para Supabase
- Habilitar RLS en todas las tablas (`pg_tables.rowsecurity = true`)
- Reemplazar políticas `USING (true)` o `auth.role() = authenticated` por políticas específicas
- Confirmar que service_role solo se usa en backend, nunca con prefijo público
- Validar inputs en todas las Edge Functions con Zod
- Configurar políticas para cada Storage bucket
- Probar consulta desde la consola sin estar logueado: debe retornar 0 filas
- Probar lectura cross-user logueado como user A intentando leer datos de user B
- Configurar email-confirmación obligatoria en Authentication settings
- Rate limit en signups (Project Settings → Auth → Rate limits)
- Auditar con VibeAuditt para detectar tablas sin RLS automáticamente
// lectura relacionada
Posts relacionados
// escaneá ahora
Audita tu app Supabase gratis
VibeAuditt detecta automáticamente los errores de este checklist en menos de un minuto. Sin tarjeta, sin instalación.