Claves secretas en tu frontend: encuéntralas y corrígelas hoy
Las apps construidas con IA suelen llevar claves de API en su JavaScript. Cuáles pueden quedar expuestas, cómo hallar las que no y en qué orden corregirlas.
En esta página · 4 secciones
Puntos clave
- Todo lo que está en el frontend de tu app es público, incluida cada clave de API empaquetada en su JavaScript. Una empresa de seguridad encontró más de 400 secrets expuestos al analizar 5.600 apps construidas con IA.
- Algunas claves están diseñadas para ser públicas (la publishable de Supabase, la publishable de Stripe). Otras nunca deben llegar al navegador (la secret de Supabase, la secret de Stripe, OpenAI y otras APIs de pago).
- Si una clave secreta estuvo alguna vez en tu frontend, rótala primero y luego mueve al servidor la llamada que depende de ella.
Todo constructor de apps con IA hace la misma concesión: la forma más rápida de hacer que una funcionalidad funcione es llamar al servicio directamente desde el navegador. Funciona, y además pone la clave de ese servicio en el JavaScript que descarga cada visitante. Cualquiera que abra las herramientas de desarrollo del navegador puede copiarla.
Este post cubre qué claves pueden quedar expuestas, cómo encontrar las que no y qué hacer cuando encuentres una. Forma parte de la guía para preparar un prototipo construido con IA para usuarios reales; para las reglas de acceso a la base de datos, consulta Supabase RLS: ¿tu app construida con IA está filtrando datos?
¿Qué tan comunes son las claves filtradas en las apps construidas con IA?
Mucho. Escape, una empresa de seguridad, analizó 5.600 apps construidas con herramientas de programación con IA y reportó más de 2.000 vulnerabilidades altamente críticas, más de 400 secrets expuestos y 175 casos de datos personales expuestos, incluidos datos de cuentas bancarias (Escape).
La causa es estructural. Las herramientas de build insertan en el JavaScript, al momento del build, las variables de entorno que tienen un prefijo público. La documentación de Vite advierte que las variables VITE_ “no deben contener información sensible, como claves de API”, porque “los valores de estas variables se empaquetan en tu código fuente al momento del build” (Vite). Next.js hace lo mismo con el prefijo NEXT_PUBLIC_ (Next.js). Una herramienta de IA que agrega el prefijo para hacer desaparecer un error acaba de publicar la clave.
¿Qué claves son seguras en el navegador?
| Clave | ¿Segura en el frontend? | Por qué |
|---|---|---|
| Clave publishable (anon) de Supabase | Sí, con RLS en todas las tablas | Solo identifica el proyecto; las policies deciden a qué puede acceder |
| Clave secret (service role) de Supabase | Nunca | Omite todas las policies de row level security |
Clave publicable de Stripe (pk_…) | Sí | Está pensada para el navegador y por sí sola no puede leer tu cuenta ni mover dinero |
Clave secreta de Stripe (sk_…) | Nunca | Puede crear cobros y reembolsos y leer todos los datos de pago |
| Claves de API de OpenAI, Anthropic y otras IA | Nunca | Cualquiera puede gastar tu crédito con ella |
| Cadenas de conexión de email, SMS y bases de datos | Nunca | Cualquiera puede enviar mensajes en tu nombre o leer tus datos |
Supabase es explícito sobre la segunda fila: “Una clave secret filtrada expone todos los datos de tu proyecto”, y las claves secret “omiten todas las políticas de Row Level Security que tengas. Nunca pongas una en un navegador, en una aplicación distribuida ni en el control de versiones” (Supabase).
¿Cómo encuentras claves expuestas?
Busca en el sitio en producción. Abre tu app, abre las herramientas de desarrollo del navegador, ve a la pestaña Sources (o Debugger) y busca en todos los archivos sk_, service_role, secret, api_key, token y los nombres de los servicios que usas. Revisa también la pestaña Network: una solicitud que va del navegador directamente a una API de pago lleva su clave.
Busca en el código y en su historial. Busca variables de entorno con un prefijo público (VITE_, NEXT_PUBLIC_, EXPO_PUBLIC_) que contengan algo distinto de identificadores públicos. Luego busca en el historial de git, no solo en los archivos actuales: una clave que se commiteó y después se borró sigue en el historial, y sigue siendo válida.
Activa el secret scanning. Si el código está en GitHub, activa el secret scanning y la push protection en el repositorio. Detectan formatos de clave conocidos en los commits y bloquean el push de claves nuevas.
¿Qué haces cuando encuentras una?
Trabaja en este orden:
- Rota la clave. Crea una clave nueva en el dashboard del proveedor y revoca la anterior. Asume que la clave anterior fue copiada; no tienes forma de saber que no lo fue.
- Revisa el daño. Mira el uso y los logs del proveedor desde que la clave quedó expuesta: gastos inesperados en APIs de IA, emails que no enviaste, lecturas de la base de datos desde lugares desconocidos.
- Mueve la llamada al servidor. El navegador llama a tu servidor (una Supabase Edge Function, un route handler de Next.js, cualquier backend pequeño), y solo el servidor guarda la clave. El servidor también decide quién puede hacer la llamada y con qué frecuencia.
- Agrega límites. Configura topes de gasto o alertas de presupuesto en las APIs de pago y rate limits en tus propios endpoints, para que un error futuro cueste poco.
El paso 3 es el que las herramientas de IA se saltan, porque requiere una pieza en el servidor que el prototipo no tenía. Por lo general es un cambio pequeño: una función por cada servicio externo.
Preguntas frecuentes
¿Es seguro poner una clave de API en una app de Vite o React?
Solo si la clave está diseñada para ser pública, como la clave publishable de Supabase o la clave publicable de Stripe. Todo lo que tenga el prefijo VITE_ o NEXT_PUBLIC_ termina en el JavaScript que se envía a cada visitante, así que las claves secretas deben quedarse en el servidor.
¿Qué pasa si mi clave de API de OpenAI queda expuesta?
Cualquiera que la copie puede hacer solicitudes que se cobran a tu cuenta hasta que la revoques. Revoca y reemplaza la clave, revisa tu uso en busca de gastos inesperados y mueve las llamadas a un endpoint en el servidor que guarde la clave nueva.
¿Borrar una clave del código soluciona la filtración?
No. La clave sigue siendo válida, sigue en tu historial de git y quizá ya fue copiada. Primero rótala en el dashboard del proveedor; quitarla del código viene después.