Saltar al contenido

Supabase exposed schemas: qué abre la lista

Supabase

Ver como MarkdownAbrir en ClaudeAbrir en ChatGPTAbrir en Perplexity

La pregunta también se copia. Si el chat se abre vacío, péguela.

En resumen

La lista Exposed schemas de Supabase decide qué esquemas sirve la Data API a cualquiera que tenga su clave pública. Por defecto son public y graphql_public. Cada tabla, vista y función de un esquema de esa lista necesita sus propios grants y su RLS, así que cada esquema extra es más superficie que defender. Mantenga la lista corta y revísela primero.

Construí un verificador de seguridad de Supabase gratuito, y la lista de Exposed schemas es una de las primeras cosas que lee. Cuando alguien me pregunta qué tan seguro es un proyecto de Supabase, empiezo por este ajuste.

¿Qué significa exponer un esquema en Supabase?

Supabase sirve su base de datos por REST con PostgREST. PostgREST solo responde por los esquemas de su lista db_schema, que se edita en el Dashboard en Project Settings → Data API → Exposed schemas. En la configuración de proyecto que miré, el valor era public,graphql_public, y la guía de esquemas personalizados de Supabase dice que public está expuesto por defecto. Una petición a un esquema fuera de la lista se rechaza, y PostgREST nunca permite pg_catalog ni information_schema en ella.

¿Por qué importa la lista para la seguridad?

Todo lo que hay dentro de un esquema expuesto es accesible con la clave pública: tablas, vistas y funciones. La guía de RLS de Supabase es directa: una tabla de un esquema expuesto sin RLS puede leerla y escribirla cualquier rol con un grant sobre ella. Un esquema que no está en la lista no se alcanza por la API de ninguna manera.

Así que un esquema extra no es un cambio neutro. Añada storage o vault a la lista y habrá puesto tablas internas al alcance de la Data API. Añada su propio esquema y cada tabla de él necesita el mismo cuidado que public.

Qué abre un esquema expuesto de más. Una petición anon, antes y después de recortar la lista. Antes: hay un esquema extra expuesto: petición anon → Data API → esquema extra → tabla sin RLS legible; Después: solo public y graphql_public: petición anon → Data API → solo esquemas por defecto → RLS en cada tabla.
De las reglas del verificador de seguridad de Supabase y la documentación de la Data API de Supabase, 22 de octubre de 2026.

¿Cómo califica el verificador los esquemas extra?

La comprobación se llama extra_exposed_schemas. Todo lo que no sea public ni graphql_public cuenta como extra, y entonces:

  • Un esquema interno de Supabase en la lista (auth, storage, realtime, vault, extensions y similares) es un problema de gravedad alta.
  • Solo esquemas propios, por ejemplo api, dan una advertencia de gravedad media.
  • Sin extras, la comprobación pasa.

La misma lista alimenta otras comprobaciones. Las tablas sin RLS, los grants de escritura para anon, las políticas siempre verdaderas, las vistas sin security_invoker y las funciones SECURITY DEFINER que anon puede llamar solo se reportan en los esquemas expuestos, porque ahí es donde la clave pública llega a ellas.

¿Cómo usar un esquema propio de forma segura?

Un esquema propio es un patrón legítimo: la guía Securing your API de Supabase describe un esquema dedicado como api como una forma de que la superficie expuesta sea más fácil de identificar y auditar, con las tablas internas en esquemas que no se exponen. Dos pasos lo hacen funcionar, y la guía de esquemas personalizados da los dos: añadir el esquema a Exposed schemas y luego conceder usage sobre él a anon, authenticated y service_role, además de privilegios sobre sus objetos.

El ejemplo de la guía concede ALL sobre cada tabla. Yo no copiaría esa línea tal cual. La guía Securing your API dice que se dé a cada rol el mínimo que necesita y que se active RLS en cada tabla que se exponga. Los grants deciden si un rol puede tocar una tabla, las políticas deciden qué filas.

Un cambio aparte: Supabase deja de conceder automáticamente las tablas nuevas de public a la Data API. Es el comportamiento por defecto de los proyectos nuevos desde el 30 de mayo de 2026 y se aplicará a los proyectos existentes el 30 de octubre de 2026, y las tablas existentes conservan sus grants. Esa es la capa de los grants. No cambia qué esquemas están en la lista.

¿Es seguro su proyecto de Supabase? Cómo comprobarlo

Abra Project Settings → Data API y lea Exposed schemas. Si hay más que public y graphql_public, pregúntese para qué sirve cada esquema extra.

Después liste las tablas de esos esquemas que tienen RLS desactivado, y si anon ya puede leerlas:

select n.nspname as schema,
       c.relname as "table",
       has_table_privilege('anon', c.oid, 'select') as anon_can_select
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname in ('public', 'api')  -- your Exposed schemas
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1, 2;

La ejecuté en un Postgres 17 desechable con un esquema api que tenía una tabla con RLS y otra sin él, más una tabla public sin RLS. Devolvió solo las dos sin RLS:

 schema | table  | anon_can_select
--------+--------+-----------------
 api    | orders | t
 public | logs   | t

Cada fila con anon_can_select en true es una tabla que cualquiera con su clave pública puede leer, hasta que active RLS o revoque el grant. La consulta cubre solo tablas. Las vistas y las funciones necesitan su propia revisión, que recorre mi lista de seguridad para apps Lovable, y cómo pruebo el RLS de Supabase muestra cómo demostrar que las políticas funcionan.

© 2026 Denys Zaichenko. Artículo original: https://madsalt.tech/es/notes/supabase-exposed-schemas/