Se filtró la service_role key de Supabase: qué hacer ya
Plan paso a paso si se filtró tu service_role o secret key de Supabase: reemplazarla, apagar la vieja, revisar qué se tocó y evitar que vuelva a pasar.
Read in English →
Si se filtró tu service_role key o una clave sb_secret_ de Supabase, da por hecho que alguien puede leer, cambiar y borrar todo lo que hay en tu base de datos y en Storage, porque esa clave se salta Row Level Security. En la próxima hora: crea una clave secret nueva, cambia tu código de servidor para que la use y después desactiva o elimina la vieja. Luego revisa los logs y los datos para ver si algo se tocó, y borra la clave del lugar por donde se escapó.
Esta guía recorre esa hora en orden y después explica cómo buscar daños y cómo evitar que la próxima clave termine en el lugar equivocado.
¿Cómo sé si de verdad se filtró?
Considérala filtrada si pasa cualquiera de estas cosas:
- Aparece en el código que descarga el navegador. Abre tu sitio en producción, entra a las herramientas de desarrollador (pestaña Sources) y busca
service_role,sb_secret_o los primeros caracteres de la clave. - Alguna vez se subió a un repositorio público de GitHub, aunque después la hayas borrado. El historial de git la conserva.
- Está en una variable de entorno con prefijo público, como
VITE_,NEXT_PUBLIC_oEXPO_PUBLIC_. Esos valores se empaquetan en el código del sitio. - La pegaste en un chat, un ticket de soporte, una captura de pantalla o un documento compartido.
- GitHub u otra herramienta de escaneo te avisó.
Para distinguir las claves: las heredadas son JWT largos que empiezan con eyJ. La anon heredada está pensada para ser pública; la service_role, no. Las nuevas son cadenas cortas que empiezan con sb_publishable_ (pública) o sb_secret_ (privada). Si no sabes cuál se filtró, decodifica el contenido del JWT: el campo role dirá anon o service_role.
¿Qué hago en la primera hora?
Sigue este orden. Reemplazar la clave antes de apagar la vieja evita que tu propia app se caiga en medio del incidente.
1. Crea una clave secret nueva
En el panel de Supabase, entra a Settings > API Keys y crea una clave secret nueva. La documentación de API keys recomienda tener una clave con nombre por cada componente del backend, para poder rotar una sin tocar las demás. Ponle un nombre claro, por ejemplo webhooks-2026-10.
2. Usa la nueva clave en todos los lugares donde estaba la vieja
Haz la lista antes de empezar. Los sitios típicos son:
- Los secretos de tus Edge Functions. Además, las Edge Functions reciben las claves nuevas automáticamente en la variable
SUPABASE_SECRET_KEYS, un objeto JSON con las claves por nombre. - Las variables de entorno de tu hosting (Vercel, Netlify, Render, Railway).
- Tareas programadas, scripts y herramientas de automatización como n8n o Zapier.
- Los archivos
.enven la computadora de cada persona que trabaja en el proyecto.
Vuelve a desplegar cada servicio después de cambiar la variable. La mayoría de los hostings solo leen las variables al compilar o al arrancar.
3. Apaga la clave vieja
- Si se filtró una clave nueva
sb_secret_: elimínala en Settings > API Keys cuando todos los servicios ya usen la nueva. Supabase advierte que eliminar una clave secret no se puede deshacer, así que confirma antes que la nueva funciona. - Si se filtró la
service_roleheredada: desactiva las claves heredadas en esa misma pantalla. Este paso es reversible: si algo que olvidaste deja de funcionar, puedes reactivarlas un momento. Si tu frontend todavía usa laanonheredada, cámbiala por una clave publishable en el mismo movimiento para que nada dependa de las claves viejas.
Las claves heredadas son JWT firmados con el JWT secret heredado del proyecto. Si sospechas que se expuso el propio JWT secret (no solo la clave), revisa la guía de JWT signing keys: la solución es pasar a signing keys y revocar el secreto heredado, y revocarlo de inmediato puede cerrar la sesión de tus usuarios.
4. Quita la clave de donde se filtró
Bórrala de donde estaba. Si estaba en un repositorio público, borrar el archivo no alcanza, pero no hace falta reescribir el historial con prisa: una vez que la clave está muerta, la copia del historial no sirve para nada. Límpialo después, con calma.
¿Cómo reviso si alguien la usó?
Cuando la clave vieja ya no funciona, se detiene el reloj. Ahora toca mirar hacia atrás.
- Revisa los logs de la API en la sección de logs del proyecto, buscando tráfico raro en el periodo en que la clave estuvo expuesta: peticiones a horas extrañas, IP desconocidas, lecturas masivas de tablas completas o borrados. Cuánto tiempo se guardan depende del plan (la página de precios de Supabase indica 1 día en Free, 7 en Pro y 28 en Team), así que revisa hoy y no la semana que viene.
- Mira los usuarios de Auth. En Authentication > Users, ordena por fecha de creación y busca cuentas que no reconozcas, sobre todo con roles de administrador en
app_metadata. - Compara la cantidad de filas de las tablas importantes con lo que esperas. Una caída brusca indica borrados; un salto en
profilesuordersindica inserciones. - Revisa Storage por archivos que falten o que no conozcas.
Si encuentras daños, restaura desde el último respaldo bueno. Los respaldos de Supabase cubren la base de datos, no los archivos de Storage, así que los archivos borrados tienen que salir de tus propias copias. En respaldos de Supabase explicamos qué guarda cada plan.
¿Tengo que avisar a mis usuarios?
Depende de qué datos quedaron expuestos, dónde viven tus usuarios y qué exige la ley allí. Muchas leyes de protección de datos tienen reglas de notificación con plazos. Esto no es asesoría legal: si pudo haber acceso a datos personales, habla pronto con un abogado. Nuestra guía sencilla sobre protección de datos para tu app te ayuda a preparar esa conversación.
¿Por qué terminó la clave en el frontend?
En apps hechas con IA, casi siempre es por una de estas razones:
- Se "arregló" un error de permisos con la clave equivocada. RLS bloqueó una consulta, la IA sugirió usar la service role key y el error desapareció. El arreglo real era una política.
- Código de servidor escrito como código de cliente. Una acción de administrador, un webhook o una importación de datos se construyó como un componente de React que llama a Supabase directamente.
- Una variable con prefijo público. El secreto se llamó
VITE_SUPABASE_SERVICE_KEYpara que el navegador pudiera leerlo.
¿Cómo evito que vuelva a pasar?
- Guarda las claves secret solo en lugares del lado del servidor: secretos de Edge Functions y variables privadas de tu hosting.
- Cuando una consulta falle por permisos, corrige la política en lugar de cambiar de clave. Mira nuestros ejemplos de políticas RLS.
- Mueve las acciones privilegiadas a una Edge Function que verifique quién llama antes de usar la clave secret.
- Agrega una búsqueda de
service_roleysb_secret_a tu checklist antes de cada despliegue, y activa el escaneo de secretos del repositorio si tu proveedor de git lo ofrece. - Usa una clave secret con nombre por servicio, para que la próxima rotación sea pequeña.
El mismo procedimiento sirve para claves de otros proveedores; lo vemos en clave de API expuesta en el frontend.
Respuestas rápidas
¿Tengo que rotar también la clave anon? La anon o publishable es pública por diseño, así que su filtración por sí sola no es un incidente. La de la service_role o la secret, sí.
¿Desactivar las claves heredadas cierra la sesión de mis usuarios? Desactivarlas bloquea las peticiones que las usan. El cierre de sesiones tiene que ver con el JWT secret heredado, no con las API keys. Planea los dos cambios por separado.
¿El bloqueo de claves secret en navegadores me protege? No. Supabase rechaza claves secret enviadas desde un navegador, pero cualquiera puede usar una clave filtrada desde un script o una terminal.
¿Cuánto tiempo tengo? Hay herramientas automáticas buscando claves en repositorios y sitios públicos todo el tiempo. Actúa como si alguien ya la hubiera encontrado.
¿Necesitas ayuda ahora?
Si no tienes claro si la filtración está contenida, una revisión de seguridad de Supabase revisa claves, políticas y funciones de punta a punta, y la revisión gratuita de tu app muestra lo que tu sitio expone en este momento. También puedes escribirnos y contarnos qué pasó.


