Saltar al contenido
← Volver al blog
appsseguridad

Variables de entorno en Bolt: qué va en cada lugar

Qué valores de una app de Bolt.new pueden ir en el navegador, cuáles van en Secrets, cómo funcionan VITE_ y otros prefijos y cómo revisar que nada se filtró.

Por Equipo Devonauts5 min de lectura
Read in English →
Una caja fuerte electrónica pequeña con teclado numérico y un juego de llaves puesto en la cerradura

Una app de Bolt.new maneja dos tipos de configuración. Lo público que necesita el navegador, como la URL de Supabase, la clave publishable o anon de Supabase y la clave publicable de Stripe, va en el archivo .env del proyecto con el prefijo público del framework (VITE_ en la mayoría de los proyectos de Bolt). Los secretos, como la clave secreta de Stripe, una clave de OpenAI o la clave secreta de Supabase, van en Secrets dentro de Bolt y solo los leen las funciones de servidor. Todo lo que lleva prefijo público termina en el JavaScript que descarga cada visitante.

A continuación tienes una tabla con los valores más comunes y su lugar, cómo funcionan los prefijos, dónde se configuran en Bolt y en otros servicios, y cómo revisar tu app publicada en busca de claves filtradas.

¿Dónde va cada valor?

Valor¿Puede estar en el navegador?Dónde va
URL del proyecto de SupabaseSí.env, como VITE_SUPABASE_URL o similar
Clave publishable de Supabase (sb_publishable_...) o la anon antiguaSí, con RLS en todas las tablas.env
Clave secreta de Supabase (sb_secret_...) o la service_role antiguaNo, se salta RLSSecrets, solo en funciones de servidor
Clave publicable de Stripe (pk_test_..., pk_live_...)Sí.env
Clave secreta de Stripe (sk_...) y secreto de firma de webhooks (whsec_...)NoSecrets
Claves de OpenAI, Anthropic, Resend y otras APIsNoSecrets
Clave de Google Maps para navegadorSí, si está restringida a tus dominios.env
Banderas de funciones, nombre de la app, URLs públicasSí.env

La regla detrás de la tabla: si conocer el valor le permite a alguien gastar tu dinero, leer datos de otras personas o hacerse pasar por tu app, es un secreto.

¿Cómo funcionan VITE_, NEXT_PUBLIC_ y EXPO_PUBLIC_?

El prefijo es lo que usa el framework para decidir qué copia dentro del paquete del navegador. La documentación de Vite indica que solo las variables que empiezan con VITE_ llegan al código del cliente, mediante import.meta.env. Next.js hace lo mismo con NEXT_PUBLIC_ y Expo con EXPO_PUBLIC_.

O sea, el prefijo es una etiqueta que dice "esto es público". El error típico es justo al revés de lo que uno espera: renombrar un secreto a VITE_OPENAI_API_KEY para que el frontend "lo vea". Funciona, y desde ese momento la clave está en un archivo que cualquiera abre con las herramientas de desarrollo del navegador. Las llamadas que necesitan un secreto tienen que pasar por una función de servidor.

¿Dónde se configuran en Bolt?

Los valores públicos

Abre la vista de código y busca un archivo .env en la raíz. Edítalo ahí o pídele a Bolt que lo cree. Si no sabes qué variables espera la app, la ayuda de Bolt sugiere preguntar: List every environment variable the application requires and where each value can be found.

Los secretos

Haz clic en el icono de base de datos arriba del proyecto y luego en Secrets. Escribe un Name que coincida con el que lee la función (por ejemplo OPENAI_API_KEY) y el Value, y guarda. Según la documentación de secretos de Bolt:

  • Bolt suele pedirte el secreto después de escribir código que lo necesita, y muestra un aviso Missing secrets con los que el código usa pero todavía no existen.
  • Un secreto nuevo queda disponible para las funciones de servidor al instante, sin volver a desplegar.
  • Solo el dueño del proyecto, los co-owners y los administradores del equipo pueden verlos o editarlos.
  • Si tu base es un proyecto de Supabase que conectaste o reclamaste, los mismos secretos aparecen en el panel de Supabase en Edge Functions > Secrets.

Dentro de una función de servidor, que corre sobre las Edge Functions de Supabase (basadas en Deno), un secreto se lee así:

const apiKey = Deno.env.get('OPENAI_API_KEY');
if (!apiKey) {
  return new Response('Server is missing OPENAI_API_KEY', { status: 500 });
}

En otro hosting

Si Netlify, Vercel u otro servicio compila tu app desde GitHub, no ve el .env de Bolt. Agrega ahí las variables públicas y recompila, porque los valores VITE_ quedan fijos al compilar. Los secretos de las funciones de servidor se quedan en Bolt o Supabase; el hosting nunca los necesita. Qué pasa cuando faltan lo contamos en error al publicar Bolt en Netlify.

¿Cómo separo los valores de prueba y de producción?

Usa valores distintos para pruebas y para producción, no solo apps distintas. En Stripe, las claves de prueba empiezan con pk_test_ y sk_test_, las reales con pk_live_ y sk_live_, y cada modo tiene su propio secreto de firma de webhooks. Un clásico del día del lanzamiento: cambiar la clave publicable a la real mientras la función de servidor sigue con la clave secreta de prueba. En variables de entorno de producción y preview mostramos una forma simple de ordenar ambas.

¿Cómo reviso que no se filtró ningún secreto?

  1. Busca en los archivos compilados. Ejecuta npm run build en la terminal de Bolt y busca prefijos delatores en la carpeta de salida:

    grep -rE "sk_live|sk_test|sb_secret|service_role|whsec_" dist/

    Lo ideal es que no aparezca nada.

  2. Busca en el sitio publicado. Abre tu app y las herramientas de desarrollo del navegador. En el panel Sources, busca en todos los archivos esos mismos prefijos y los nombres de tus proveedores de API.
  3. Revisa GitHub. Confirma que .env está en .gitignore y que ningún commit anterior tiene claves reales. Una clave que alguna vez se subió hay que tratarla como pública.
  4. Corre la auditoría de seguridad de Bolt. En los planes de pago, Run security audit en el menú Publish revisa que las claves privadas no estén en el código ni se envíen al navegador, y no gasta tokens.

Si encuentras un secreto donde no debe estar, moverlo no alcanza. Rótalo en el panel del proveedor (crea una clave nueva, actualiza Secrets y borra la vieja), porque alguien ya pudo copiarla. En clave de API expuesta en el frontend explicamos esa limpieza paso a paso.

Respuestas rápidas

¿La clave anon de Supabase es secreta? No. Está pensada para ser pública y lo que protege los datos es Row Level Security. La que nunca debe llegar al navegador es la service_role o la secreta.

¿Por qué mi variable sale undefined? O le falta el prefijo VITE_, o la agregaste después del último build, o no reiniciaste el servidor de desarrollo tras editar el .env.

¿Puedo poner secretos en el .env si el repositorio es privado? No para nada que lea el frontend. El repositorio privado protege el código fuente, pero el JavaScript compilado sigue siendo público en tu sitio.

¿Tengo que volver a desplegar después de cambiar un secreto en Bolt? Para las funciones de servidor no, según la documentación de Bolt. Los cambios en valores VITE_ sí necesitan un build nuevo.

¿No sabes qué está exponiendo tu app?

La revisión gratuita mira tu app publicada desde afuera, que es justo donde aparecen las claves filtradas. Para una revisión completa de claves, políticas y funciones de servidor, mira nuestra revisión de seguridad de Supabase y el servicio para arreglar apps de Bolt, o escríbenos.

¿Tu app sigue trabada?

Pasa el chequeo gratis con la URL de tu app, o pide la Auditoría de rescate de $299: un ingeniero senior revisa el código y te envía un informe escrito en 2 días hábiles.