Saltar al contenido

Fundamentos de seguridad

Una clave secreta de Stripe en tu frontend puede mover dinero

Una clave secreta de Stripe expuesta en tu frontend puede reembolsar, cobrar y leer cada ficha de cliente que tienes. Tu clave pk_live_ sí debe estar ahí.

Vlad Tkachenko11 min de lectura
Una caja registradora de tienda con el cajón del dinero abierto y una llave olvidada en la cerradura del frente de la máquina.

En resumen

  • Una clave secreta de Stripe expuesta en tu frontend es la fuga que se cobra a tu cuenta: reembolsos, cargos nuevos y cada ficha de cliente que tienes.
  • pk_live_ pertenece a tu app y siempre fue así. sk_live_ se diferencia en un solo carácter y tiene permisos sin restricción sobre toda tu cuenta de Stripe.
  • Crea primero la clave de repuesto, ponla en producción y solo entonces caduca la vieja. Borrar la línea de tu código no recupera nada que alguien ya descargó.
  • Encontramos una clave secreta de Stripe activa en 3 de 30.998 apps escaneadas. Las tres salieron con nota D.

Abre tu app en producción en un navegador, mira el código fuente de la página y busca dentro sk_live_. Si aparece una cadena larga, tienes una clave secreta de Stripe expuesta en tu frontend, y cualquier visitante que hayas tenido podría haberla copiado.

Aquí está la parte que el consejo general sobre claves de API se equivoca: Stripe te da dos claves activas, se parecen muchísimo, y una de ellas debe estar en tu app. La clave que empieza por pk_live_ pertenece ahí. La clave que empieza por sk_live_ tiene, en palabras de Stripe, permisos sin restricción sobre todas las APIs. Se diferencian en un carácter en medio de una cadena larga, y eso explica la mayor parte de por qué esto sigue pasando.

Entre el 12 y el 14 de agosto de 2026 pasamos nueve comprobaciones externas a 30.998 apps en producción construidas con Lovable, Bolt, v0, Replit y Base44. Tres de ellas entregaban una clave secreta de Stripe activa, y otras dos una restringida, lo que la convierte en una de las cosas más raras que encontró el barrido; esas mismas nueve comprobaciones encontraron una clave de API de Google en 1.142 apps. Las tres claves secretas salieron con nota D, porque un único hallazgo crítico tapa la nota ahí por bien que esté todo lo demás. Los números completos están en nuestro informe de escaneo.

¿Es un problema una clave secreta de Stripe expuesta en tu frontend?

Sí, si la cadena empieza por sk_live_. No, si empieza por pk_live_.

Stripe emite dos claves activas porque las dos mitades de un pago ocurren en dos sitios distintos. Imagina el mostrador de una tienda. El datáfono mira hacia la clientela y está atornillado a la vista de todos, y lo peor que un desconocido puede hacer con él es pagarte. La caja registradora detrás del mostrador es otra cosa por completo. Se abre, guarda la recaudación del día, y en el cajón de debajo hay una ficha por cada cliente con su dirección escrita.

pk_live_ es el datáfono. Su trabajo es construir un formulario de pago dentro del navegador de otra persona, y la documentación de Stripe dice que las claves publicables se pueden exponer sin problema en el código del frontend.

sk_live_ es la llave de la caja. Stripe describe las claves secretas como claves con permisos sin restricción sobre todas las APIs, que es la misma frase leída del otro lado: no hay nada en tu cuenta que no alcance.

Tu app necesita el datáfono en el navegador para poder cobrar siquiera. La llave de la caja no debería necesitarla nunca.

pk_live_ y sk_live_: cómo distinguirlas

Lee el segundo carácter del prefijo. Esa es toda la prueba.

ClaveEmpieza por¿Segura en el navegador?Qué hace
Publicablepk_live_…Su sitioConstruye el formulario de pago y tokeniza una tarjeta. No lee clientes ni mueve dinero.
Secretask_live_…NuncaPermisos sin restricción sobre todas las APIs de Stripe, en toda tu cuenta.
Restringidark_live_…NuncaSolo los permisos que marcaste al crearla. Sigue siendo una credencial válida en manos ajenas.
De pruebask_test_, pk_test_NoSolo toca tu entorno de pruebas. Un problema menor con la misma costumbre detrás.

La parte del medio del prefijo es lo segundo que hay que leer. _test_ no alcanza nada fuera de tu entorno de pruebas, así que una clave de prueba filtrada no te cuesta dinero; aun así publica cómo está construida tu integración, y la guía de Stripe es tratar como comprometida cualquier clave secreta o restringida que aparezca donde no debía. Las cuentas más nuevas pueden llevar además una clave de organización que empieza por sk_org_ y que opera sobre más de una cuenta de Stripe a la vez. Sigue la misma regla, y una fuga ahí llega más lejos que una sola cuenta.

Qué puede hacer alguien con una clave secreta de Stripe filtrada

Todo lo que tú puedes hacer en tu propio panel y que no pida tu contraseña.

No "obtener acceso no autorizado". En concreto, sin más que la cadena y una terminal: leer tu lista completa de clientes, con nombres, correos, direcciones de facturación y los cuatro últimos dígitos de cada tarjeta. Leer todos los pagos que has cobrado, y por qué pagó cada cliente. Emitir reembolsos. Crear cargos y enlaces de pago en tu nombre. Cancelar suscripciones.

Las dos claves están en el mismo archivo. La segunda columna es lo que compra ese carácter de más, y cada marca roja es una petición que sale bien.

Luego está el uso que no tiene nada que ver contigo. Tu cuenta se convierte en un sitio donde hacer card testing, el término del propio Stripe para un estafador que pasa números de tarjeta robados por la integración de cualquiera hasta dar con los que siguen funcionando. Las tarjetas son de otras personas. Los rechazos, los contracargos y las explicaciones son tuyos.

Lo que en general no pueden hacer es pagarse a sí mismos. Un reembolso vuelve a la tarjeta que hizo el pago original, y una transferencia de fondos va a la cuenta bancaria registrada, que es la tuya. Suena a buena noticia y no lo es: significa que el daño llega como dinero tuyo que se va, fichas de tus clientes copiadas y tu cuenta usada para el fraude de otro, en lugar de como una transferencia que pudieras señalar y perseguir.

Nada de esto exige un atacante sofisticado. La propia documentación de Stripe dice que hay actores fraudulentos rastreando sin parar bases de código públicas en busca de claves expuestas, y esos rastreadores no necesitan saber quién eres para encontrar la tuya.

Cómo rotar una clave secreta de Stripe sin cortar los cobros

Crea primero el repuesto, ponlo en producción y solo entonces caduca la vieja. En ese orden.

  1. En el panel de Stripe, crea una clave secreta nueva. Deja la vieja en paz por ahora; las dos funcionan a la vez, y ese solape es lo que mantiene tu checkout en marcha.
  2. Pon la clave nueva donde vivía la vieja, y eso debería ser un servidor, una Edge Function o una ruta serverless. Nunca la app que descarga el navegador.
  3. Despliega y luego cobra un pago real. Un cobro que sale bien es la única prueba de que la clave nueva está bien conectada.
  4. Caduca la clave vieja. Stripe lo describe igual: caducar una clave secreta o restringida le impide hacer cualquier otra llamada a la API.
  5. Lee tu historial de pagos del periodo en que la clave estuvo expuesta, y tu correo de Stripe por si hay algo que no hiciste tú.

Si la clave ya está fuera y prefieres perder unos cuantos pagos antes que dejarla activa una hora más, hazlo al revés. Rotar una clave la bloquea de inmediato y genera una nueva, y Stripe señala que los endpoints de webhook creados con la clave vieja siguen activos, así que tu procesamiento de eventos sobrevive a la emergencia.

El solape del panel del medio es lo importante. Las dos claves están activas a la vez, y eso es lo que permite el cambio sin un hueco en tu checkout.

Queda un paso más, y es el que casi todo el mundo hace primero: borrar la clave de tu código. Hazlo, y ten claro qué consigue. Tus visitantes ya descargaron el archivo que la llevaba, ese archivo está en cachés de navegador que no controlas, y el valor viejo sigue en tu historial de versiones. Caducar la clave en Stripe es lo que cierra la puerta. Quitar la línea es lo que te impide volver a enviarla.

Las claves publicables, por cierto, no se pueden caducar en absoluto. Stripe nunca construyó ese control, porque esa clave nunca fue algo que hubiera que guardar.

Qué es una clave restringida de Stripe y cuándo es la respuesta

Una clave cortada a medida para un trabajo en lugar de para todos.

Una clave restringida empieza por rk_live_ y lleva únicamente los permisos que marcas al crearla. Una clave que puede leer facturas no puede emitir un reembolso. Una clave que puede crear cargos no puede leer tu lista de clientes. Stripe recomienda pasar de claves secretas a restringidas justo por eso, y es un buen consejo sobre el código que corre en tu servidor.

No es una forma de hacer aceptable una clave en el navegador. Dos de las 30.998 apps de nuestro barrido entregaban una clave restringida en el frontend, y las dos salieron con nota C. Nuestro escaneo trata una clave restringida como hallazgo alto donde una secreta es crítico, y un único hallazgo alto tapa la nota en C. Quien encuentre esa clave sigue teniendo cada permiso que marcaste, desde donde sea.

Donde una clave restringida se gana su sitio es en el caso intermedio incómodo, y las apps hechas con IA producen unos cuantos. Una herramienta de automatización que necesita leer tus transferencias. Un script de informes que alguien te escribió en Fiverr. Una Edge Function que solo crea un tipo de cargo. Cada una corre en un servidor y cada una necesita una fracción de tu cuenta, así que cada una lleva su propia clave con esa fracción marcada, y el día que una se filtre revocas una clave en lugar de recablear toda tu integración.

Cómo comprobar qué está entregando tu app en realidad

Empieza a mano, porque no cuesta nada y no hace falta instalar nada. Abre tu sitio en producción, mira el código fuente de la página y busca dentro sk_live_, luego rk_live_, luego pk_live_. Encontrar la tercera y no las dos primeras es el resultado que quieres.

Lo que una búsqueda en el código fuente se pierde es el JavaScript que la página carga después, y en una app hecha con Lovable, Bolt o Replit eso es casi todo. Nuestro escáner gratuito abre tu app en un navegador de verdad, espera a que lleguen los bundles y lee esos. Clasifica lo que encuentra en lugar de buscar cadenas con forma de clave, así que pk_live_ vuelve marcada como correcta y sk_live_ vuelve como hallazgo crítico, y las dos nunca acaban en el mismo montón.

Las claves son una de nueve comprobaciones de solo lectura. Las demás son por qué una nota te dice más que una búsqueda en tu propio código fuente.

La nota, la puntuación y los recuentos aparecen en pantalla en unos 20 segundos, sin cuenta. Si das un correo, llega con la lista detallada, junto con una solución escrita para el builder que usaste y que puedes pegar tal cual.

Tres cosas que el escaneo no hace, y son las razones por las que puedes apuntarlo sin miedo a una app en producción que cobra de verdad: nunca inicia sesión, nunca escribe nada, y nunca se queda con una clave que encuentra. Un secreto expuesto se guarda como una pista enmascarada de la forma sk_live_…a1b2, y el valor real se tira. Escanea tu app, o lee antes qué mira cada una de las nueve comprobaciones.

Qué hacer ahora mismo

Qué hacer

  • Lee el segundo carácter antes que nada. pk_live_ en tu bundle está bien y no pide nada; sk_live_ y rk_live_ sí.
  • Crea primero la clave de repuesto y confirma un pago real con ella, y solo entonces caduca la vieja en Stripe. Caducarla es lo que cierra la puerta.
  • Borrar la clave de tu código no cierra nada por sí solo. El archivo que la llevaba ya está descargado, en caché y en tu historial de versiones.
  • Mueve a un servidor lo que necesitara esa clave: una Edge Function, una ruta serverless, cualquier cosa que no sea el navegador.
  • Lee tu historial de pagos y tu lista de clientes del periodo en que la clave estuvo activa. Rotar detiene lo que pase a partir de ahora y no dice nada de lo que ya pasó.
  • Dale a cada tarea del servidor su propia clave restringida con solo los permisos que necesita, para que la próxima fuga te cueste una clave y no todas.

Una clave de Stripe suele llegar tarde. La app sale, funciona un tiempo, y un día añades el checkout, y ese es el despliegue que mete por primera vez una credencial de cobro en el bundle. El escaneo que pasaste al lanzar era una foto de una app que todavía no podía cobrar.

Reeve Monitor está hecho para ese hueco. Pasa las nueve comprobaciones cada hora sobre hasta tres apps, vigila la disponibilidad cada 60 segundos, te avisa el día en que un resultado cambia en lugar de esperar a que mires, y manda un informe mensual en lenguaje claro. Una clave que llega al bundle con un despliegue de un jueves entra en el escaneo de esa misma hora. Cuesta $12 al mes de tarifa, con siete días gratis antes de cobrarte, y la página de precios a veces está por debajo de la cifra de aquí y nunca por encima.

Si lo prefieres como lista, la checklist de seguridad de 10 minutos cubre esto junto con las otras cosas que conviene cerrar en una app recién lanzada. Para la pregunta más amplia de qué claves pintan algo en un navegador, tenemos una guía para distinguir claves publicables de secretas, la misma pregunta para una clave de OpenAI, y un censo de lo que 30.998 apps entregaban de verdad.

Preguntas frecuentes

¿Es segura mi clave publicable de Stripe en el frontend?

Sí. Una clave que empieza por pk_live_ debe estar en la página, y Stripe lo dice en su propia documentación: las claves publicables se pueden exponer sin problema en el código del frontend. Construye el formulario de pago y tokeniza una tarjeta. No puede leer tus clientes, ni mover dinero, ni reembolsar nada. Si un escáner o un conocido te dijo que tienes una clave de Stripe expuesta, lee el segundo carácter antes de hacer cualquier otra cosa, porque una clave pk_live_ dentro de tu bundle es tu integración funcionando tal como Stripe la diseñó.

¿Qué puede hacer alguien con una clave secreta de Stripe filtrada?

Todo lo que tú puedes hacer en tu propio panel y que no pida tu contraseña. Puede leer tu lista completa de clientes con nombres, correos, direcciones de facturación y los cuatro últimos dígitos de cada tarjeta, leer todos los pagos que has cobrado, emitir reembolsos hasta vaciar tu saldo, crear cargos y enlaces de pago, y pasar números de tarjeta robados por tu cuenta para encontrar los que siguen funcionando. A esto último Stripe lo llama card testing, y a ti te llega como contracargos y rechazos en una cuenta que creías tranquila.

¿Cómo roto una clave de Stripe sin cortar los cobros?

Crea primero el repuesto. En el panel de Stripe crea una clave secreta nueva, ponla donde vivía la vieja en tu servidor, despliega y confirma un pago real con la clave nueva. Solo entonces caduca la vieja, lo que le impide hacer cualquier otra llamada a la API. Si la clave ya es pública y prefieres perder unos cuantos pagos antes que dejarla activa, rótala de golpe: rotar bloquea la clave de inmediato y genera una nueva, y Stripe señala que los endpoints de webhook creados con la clave vieja siguen activos.

¿Qué es una clave restringida de Stripe?

Una clave cortada a medida para un solo trabajo. Una clave restringida empieza por rk_live_ y lleva únicamente los permisos que marcas al crearla, de modo que una clave que puede leer facturas no puede emitir un reembolso. Stripe recomienda pasar de claves secretas a restringidas justo por eso. Léelo como un consejo sobre el código de tu servidor, no como una forma de hacer aceptable una clave en el navegador: una clave restringida dentro de tu bundle sigue siendo una credencial que un desconocido puede usar, y nuestro escaneo la califica como hallazgo alto.

¿Stripe me avisa si mi clave se filtra?

A veces, y no puedes contar con ello. Stripe dice que rastrea internet de forma activa en busca de claves de API filtradas, con herramientas como el escáner de tokens de GitHub, y que puede avisarte o desactivar una clave que encuentre. Su propia página de buenas prácticas añade que la detección no está garantizada. Ese rastreo funciona mejor sobre repositorios de código públicos, y una clave compilada dentro del JavaScript de tu propio dominio no es un repositorio. Trata como comprometida cualquier clave que hayas visto donde no debía estar, diga Stripe algo o no.

¿Una clave de prueba (sk_test_) es peligrosa en mi frontend?

Es un problema bastante menor que una clave activa y aun así conviene cerrarlo. Una clave de prueba solo toca tu entorno de pruebas, así que nadie puede llevarse tu dinero con ella. Lo que sí entrega es un mapa práctico de cómo está montada tu integración, y suele significar que la misma costumbre de copiar y pegar está a un despliegue de mandar la clave activa. Stripe trata como comprometida cualquier clave secreta o restringida que aparezca donde no debía. Caducala y mueve la llamada a un servidor.

Escrito por

Vlad Tkachenko

Fundador de Reeve

Me paso el día mirando apps creadas con Lovable, Bolt, v0, Cursor y Replit, y la corta lista de errores que aparecen en ellas una y otra vez.

Más sobre el autor

Sigue leyendo

Todos los artículos

¿No sabes cómo está tu propia app?

Haz un escaneo gratuito y obtén una nota clara de la A a la F en unos 20 segundos. Sin cuenta y sin tarjeta.

Analizar mi app gratis

Comprobación externa automatizada, no una auditoría completa. La ausencia de hallazgos no es garantía de seguridad.