¿SUPABASE ES SEGURO? ANÁLISIS DE SEGURIDAD 2026 | VIBEEVAL

RLS no es negociable

Supabase expone tu base de datos PostgreSQL directamente a los clientes vía anon key. Sin políticas de RLS, cualquier persona con la URL de tu proyecto puede leer, modificar o borrar todos los datos en las tablas desprotegidas. Esto no es un bug — es el modelo de datos. Supabase fue diseñado para que la BD sea la capa de autorización; si rompes ese modelo dejando RLS desactivado, no hay segunda línea de defensa.

El modelo mental clave: la anon key no es “la llave que solo puede leer” — es la llave que puede hacer exactamente lo que tus políticas permitan. Sin políticas, “todo está permitido”.

Problemas de seguridad comunes

Políticas de RLS ausentes

Las tablas sin RLS activo quedan totalmente accesibles para cualquiera con la anon key, llevando a exposición completa de los datos. Cualquiera que cargue tu frontend ve la URL de Supabase y la anon key en la pestaña Network de DevTools — apenas las tiene, puede llamar https://<project>.supabase.co/rest/v1/<table>?select=* directamente con curl.

Habilita RLS por tabla y escribe al menos una política:

alter table profiles enable row level security;

create policy "users read own profile"
  on profiles for select
  using ( auth.uid() = user_id );

create policy "users update own profile"
  on profiles for update
  using ( auth.uid() = user_id )
  with check ( auth.uid() = user_id );

Sin with check en update/insert, un usuario puede modificar una fila para que después del update pertenezca a otra user_id.

Filtración de la service role key

La service_role key ignora RLS. Exponerla en el código del cliente da acceso total a la BD a atacantes. Las rutas de filtración más comunes que vemos: en una env var NEXT_PUBLIC_* de Next.js (todo con ese prefijo termina en el bundle), en un repo público de GitHub bajo .env.example con valor real, o en una env var de preview de Vercel mal scoped al ambiente equivocado.

Separa estrictamente: la service role key vive solo en código de servidor (Edge Functions, API routes sin prefijo NEXT_PUBLIC_, workers de backend). Si la necesitas en el navegador, no la necesitas — necesitas una mejor política RLS.

Políticas de RLS con fallos

Las políticas de RLS con errores lógicos crean rutas de acceso no previstas. Las políticas complejas requieren pruebas exhaustivas. Trampas clásicas: definir una política solo en select y olvidar que update y delete también necesitan una; usar en una cláusula using un subquery sobre otra tabla sin RLS; o poner true como placeholder y nunca volver a poner el check real.

Escribe tests pgTAP por política y córrelos en CI — RLS sin tests es esperanza, no protección.

Mala configuración de Storage buckets

Supabase Storage también requiere RLS. Los buckets públicos pueden exponer archivos sensibles. En uploads, además, valida MIME por allowlist y pon límite de tamaño; si no, tu bucket se vuelve un CDN gratis para contenido de terceros.

create policy "users read own files"
  on storage.objects for select
  using ( bucket_id = 'avatars' and auth.uid()::text = (storage.foldername(name))[1] );

Edge Functions sin chequeo de auth

Las Edge Functions en Supabase corren con la service role key si no las configuras explícitamente de otra forma. Una Function que acepta una request y ejecuta una operación de BD sin verificar el JWT entrante es, efectivamente, un endpoint abierto que evita RLS. Verifica siempre req.headers.get('Authorization') y usa el token del usuario para el call a la BD en lugar de la service role key.

Realtime y postgres-changes

Supabase Realtime respeta RLS para suscripciones postgres_changes, pero solo si lo activas. Una suscripción a una tabla sin RLS transmite cada cambio a cada cliente conectado.

Evaluación de seguridad

Puntos fuertes

    • PostgreSQL con seguridad enterprise-grade
    • Row Level Security (RLS) para control granular de acceso
    • Autenticación embebida con tokens JWT
    • Open source — auditable en seguridad
    • Conformidad SOC 2 Type II

Preocupaciones

    • Políticas de RLS a menudo ausentes o mal configuradas
    • Configuraciones por default pueden exponer datos
    • La anon key viaja al cliente — RLS es esencial
    • Filtrar la service role key concede acceso total
    • Sintaxis compleja de RLS lleva a huecos de seguridad

Aspectos enterprise

Supabase ofrece en los planes Pro y Team SSO (SAML), audit logs para acciones del dashboard y bases de datos branch para entornos de preview aislados. Si trabajas en un contexto regulado, tres puntos son especialmente relevantes:

  • Frontera SOC 2: Supabase cumple SOC 2 Type II, pero la conformidad aplica a la plataforma — no a las políticas que tú escribes. Una política RLS ausente es un finding tuyo en la auditoría, no de Supabase.
  • Audit logs: Activa los audit logs y envíalos a S3 o Datadog. Sin logs off-site no tienes evidencia, en caso de incidente, de quién rotó la service role key o eliminó una política.
  • Branch DBs para PRs: Usa branching en lugar de copiar datos productivos a entornos de preview. Una URL de preview filtrada con datos reales de usuarios es un incidente de privacidad.

El veredicto

Supabase es seguro como plataforma, con la seguridad probada de PostgreSQL. El factor crítico es la configuración correcta de RLS. Habilita RLS en cada tabla, escribe y prueba las políticas a fondo y nunca expongas la service_role key en el código del cliente. Con la configuración correcta, Supabase ofrece excelente seguridad.

Tres chequeos antes de cada lanzamiento: (1) select * from pg_tables where rowsecurity = false and schemaname = 'public' — ¿lista vacía? Bien. (2) Grep el bundle del frontend buscando service_role y cualquier key que no sea la anon key. (3) Intenta como segundo usuario de prueba leer datos del primero. Si algo pasa, tu política está mal.

Recursos relacionados

Cómo proteger Supabase

Guía paso a paso de seguridad con patrones RLS, validación de JWT y hardening de Storage.

Checklist de seguridad de Supabase

Checklist de seguridad interactiva — desde “RLS en cada tabla” hasta “audit logs activados”.

Supabase RLS Checker

Escaneo automatizado que verifica que cada tabla de tu proyecto tenga RLS activo y al menos una política.

Token Leak Checker

Encuentra service role keys, anon keys y secretos JWT filtrados en tu bundle de frontend y en tus repos.

Riesgos de seguridad de vibe coding

Resumen de los patrones de fallo que el código generado por IA introduce típicamente en proyectos Supabase.

Escanea tu app Supabase

Deja que VibeEval revise tu aplicación Supabase en busca de mala configuración de RLS y vulnerabilidades — tablas sin políticas, keys filtradas, buckets de Storage públicos, BOLA en Edge Functions. Resultados en menos de 60 segundos, con archivo y número de línea para corregir.

COMMON QUESTIONS

01
¿Supabase es seguro como plataforma?
Sí. Supabase corre sobre PostgreSQL gestionado, cumple con SOC 2 Type II, fuerza TLS y parchea su propia infraestructura. Las vulnerabilidades que encontramos en apps Supabase casi nunca están en la plataforma — están en políticas RLS ausentes, service role keys filtradas y buckets de Storage públicos que el desarrollador configuró por su cuenta.
Q&A
02
¿Cuál es la diferencia entre la anon key y la service role key?
La anon key es pública por diseño — va en el navegador y solo es tan poderosa como tus políticas RLS lo permitan. La service role key ignora RLS por completo y otorga acceso total a cualquier tabla. La service role key nunca debe terminar en el bundle del cliente, en una env var de preview de Vercel sin scope, ni en un repo público.
Q&A
03
¿Cómo pruebo si mis políticas RLS realmente funcionan?
Autentícate con la anon key como dos usuarios de prueba diferentes y luego intenta leer los datos del otro vía `select`, `update` y `delete`. Si pasa una request que no debería pasar, tienes una brecha. Supabase ofrece `pgTAP` para tests orientados a políticas en CI.
Q&A
04
¿Necesito RLS también para los buckets de Storage?
Sí. Supabase Storage replica el mismo modelo — cada bucket es privado por default, pero apenas pones `public: true` o escribes una política que devuelve `true`, los archivos quedan legibles anónimamente. Escribe una política por bucket sobre `storage.objects` que valide `auth.uid()` contra el campo de propietario.
Q&A

ANALIZA TU APP

14 días de prueba. Sin tarjeta. Resultados en menos de 60 segundos.

INICIAR ESCANEO GRATIS