Miguel Santa 13 de mayo de 2026

No uses .env, tu computador ya tiene caja fuerte

Tu sistema operativo ya viene con un gestor de claves cifrado. La mayoría no lo usa y arriesga sus API keys en un .env. Te muestro cómo cambiar el hábito en 5 minutos.

seguridadtokenskeychainenvsecretosbásico

Primero · ¿Qué es un token y por qué tanto cuidado?

Si acabas de empezar a programar con IA, probablemente escuchaste la palabra "token" o "API key" y todavía no te queda del todo claro qué es. Vamos por ahí.

Por eso importa guardarla bien. No es paranoia. Es responsabilidad básica.

Lo que pasa cuando una llave se filtra

Esto no es teoría. Son números de un reporte público de GitGuardian (empresa de ciberseguridad que escanea GitHub a diario):

12,7M

secretos filtrados

en GitHub público durante 2023

+28%

crecimiento anual

se multiplican cada año

1.212×

API keys de OpenAI

crecimiento en un solo año (2022→2023)

Y este es el dato que más asusta:

Caso real · Toyota, 5 años expuesto

En octubre de 2022, Toyota admitió públicamente que un token de acceso a su sistema T-Connect (su plataforma conectada de autos) había estado expuesto en GitHub durante 5 años.

Lo había subido por error un subcontratista en un repositorio público. Nadie revisó. Estuvo ahí 1.825 días.

5 años

duración de la fuga

entre 2017 y 2022

296.019

clientes afectados

emails + números de cliente expuestos

$0

valor de un .env

como herramienta de seguridad

Si le pasa a Toyota, te puede pasar a ti. La diferencia es que tu llave de OpenAI no es defendida por un equipo de ciberseguridad. Es solo tuya. Si se filtra, tú pagas la cuenta.

Por eso esta guía existe.


La tesis

Tu Mac, Windows o Linux ya viene con una caja fuerte cifrada. Está ahí desde el día uno. Casi nadie la usa.

En cambio, mucha gente guarda sus llaves de OpenAI, Stripe o Anthropic en un archivo de texto plano llamado .env. Y un buen día se les filtra.

No vamos a hablar de "cuándo usar .env". Vamos a hablar de cómo dejar de usarlo.


1 · Las tres zonas donde puede vivir tu llave

¿DÓNDE VA A VIVIR TU LLAVE? archivo .env en tu discotexto planosin cifradovisible para cualquierprograma con acceso al discogestor del sistema operativoCIFRADOcifrado por el sistemase abre con tu contraseñaya viene en tu computadorno instalas nada extrapanel del proveedorsolo para producciónCloudflare Pages, VercelGitHub Actions, Railwayse inyecta solo al desplegar regla: nunca la opción 1. siempre la 2 para local, la 3 para producción.
Una llave en .env es una llave debajo del tapete. Ya hay caja fuerte en tu casa.

2 · Por qué un .env es peligroso por defecto

Un archivo .env es texto plano. Sin cifrar. Cualquiera con acceso a tu disco lo lee.

Pero el riesgo real no es ese. El riesgo real es esta cadena:

CÓMO SE FILTRA UN .ENV · LA CADENA .envOPENAI=sk-...DB_URL=...PORT=80001tu archivo .envcon la llave realgit add ..envreadmeinit2git commitqueda en historialgit pushGitHubo GitLab3subido a internetpúblico o privado, da igual24/74bots la encuentranen minutos, no en días resultado típico: $1.000+ en consumo de tu llave en menos de 1 hora
Un descuido + git add . y tu llave queda en internet para siempre.

3 · Mac · Tu Keychain ya está ahí

macOS viene con Keychain Access. Una caja fuerte cifrada con tu contraseña de usuario. La abre tu sistema cuando inicias sesión.

Guardar una llave

security add-generic-password \
  -a "santaia" \
  -s "santaia:openai-key" \
  -w "sk-proj-tu-llave-real"

Leerla desde tu código

import subprocess

def get_secret(name: str) -> str:
    return subprocess.run(
        ["security", "find-generic-password",
         "-s", name, "-a", "santaia", "-w"],
        capture_output=True, text=True, check=True
    ).stdout.strip()

openai_key = get_secret("santaia:openai-key")

Borrarla si la rotaste

security delete-generic-password -s "santaia:openai-key" -a "santaia"

4 · Windows · Credential Manager

Windows también lo tiene. Se llama Credential Manager y se maneja desde PowerShell con cmdkey.

Guardar una llave

cmdkey /generic:"santaia:openai-key" `
       /user:"santaia" `
       /pass:"sk-proj-tu-llave-real"

Leerla desde tu código

Necesitas el módulo CredentialManager (una sola vez):

Install-Module -Name CredentialManager -Scope CurrentUser

Después desde Python:

import subprocess

def get_secret(target: str) -> str:
    ps = f'(Get-StoredCredential -Target "{target}").GetNetworkCredential().Password'
    return subprocess.run(
        ["powershell", "-Command", ps],
        capture_output=True, text=True, check=True
    ).stdout.strip()

openai_key = get_secret("santaia:openai-key")

5 · Linux · secret-tool

Linux usa libsecret como API estándar. Instala la CLI una vez:

# Debian / Ubuntu
sudo apt install libsecret-tools

# Fedora
sudo dnf install libsecret

Guardar una llave

secret-tool store --label="OpenAI · santaia" \
  service "santaia" \
  key "openai-key"

Te pregunta el valor de la llave en interactivo. No queda en tu historial de bash.

Leerla desde tu código

import subprocess

def get_secret(service: str, key: str) -> str:
    return subprocess.run(
        ["secret-tool", "lookup", "service", service, "key", key],
        capture_output=True, text=True, check=True
    ).stdout.strip()

openai_key = get_secret("santaia", "openai-key")

6 · Mi convención de naming

Cuando llevas 30+ llaves entre varios proyectos, sin convención no encuentras nada. Esta es la que uso:

Para llaves globales

patrón: servicio-contexto

  • gitlab-terracomerce
  • gitlab-personal
  • anthropic-personal

Llaves que usas en varios proyectos. El sufijo dice para qué cuenta.

Para llaves de un proyecto

patrón: proyecto:servicio

  • santaia:openai-key
  • santaia:elevenlabs-key
  • santaia:gemini-key

Llaves específicas de un proyecto. Los dos puntos separan el proyecto del servicio. Fácil de filtrar:

security dump-keychain | grep santaia

7 · Producción · Nunca en tu máquina

Tu computador personal nunca debe tener llaves de producción. Punto.

Las llaves de producción viven en el panel del proveedor donde despliegas. Se inyectan solo cuando se ejecuta el build.

Cloudflare Pages

Ruta: Settings → Environment variables → Add

Pones nombre + valor + ambiente (Production / Preview). Guardas y redeploy. La variable solo existe durante el build.

Es lo que uso yo para santa-ia.com.

GitHub Actions

Ruta: Settings → Secrets and variables → Actions → New repository secret

En tu workflow lo lees con secrets.NOMBRE:

- env:
    OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
  run: npm run deploy

Vercel

Ruta: Settings → Environment Variables

Misma idea que Cloudflare: nombre + valor + ambiente. Inyección automática durante el build.

Railway

Ruta: pestaña Variables de cada servicio

Puedes importar de un .env local en bloque. Esa es la única vez que un .env tiene sentido: importarlo a Railway una vez y nunca más.


8 · ¿Y si ya filtré algo?

Te puede pasar. Si pasó, no entres en pánico. Tres pasos en orden:

SI YA FILTRASTE UNA LLAVE · 3 PASOS EN ORDEN 1 · ROTARen el serviciorevoke + crear nuevala llave vieja queda muerta2 · LIMPIARel historial gitgit filter-repoel rastro desaparece3 · ANOTARqué pasópara no repetirlo el orden importa: si limpias git antes de rotar, la llave sigue activa.
Una sola regla: rotar primero, limpiar después.

Rota la llave en el servicio

Esto primero. Mientras la llave vieja siga activa, el daño sigue creciendo.

  • OpenAI: Dashboard → API Keys → Revoke → crea nueva
  • Stripe: Dashboard → Developers → API keys → Roll
  • AWS: IAM → Access Keys → Deactivate + Delete + Create new

Cualquier servicio serio tiene un botón de "rotate" o "revoke" en su panel.

Limpia el historial de git

Para repos privados y recientes, basta con:

git rm --cached .env
echo ".env" >> .gitignore
git commit -m "chore: remove .env from tracking"
git push

Para repos públicos o historiales largos, usa git-filter-repo:

pip install git-filter-repo
git filter-repo --invert-paths --path .env
git push --force

Anota qué pasó

En el README o tu sistema de notas: qué llave se filtró, qué hiciste, qué falló en tu proceso. Sin esto, el segundo incidente cae igual.


Cierre

Si pruebas esto en algún proyecto tuyo y se te traba algo, escríbeme en @santaia.lab. Las dudas reales son el material del próximo artículo.

hecho con mucho amor

espero les sea útil

santa-ia · 2026 · @santaia.lab