Tips & Tricks (Actualizado: 2/6/2026)

Gestión de secretos con Claude Code: de .env a la rotación en producción

Guía para proteger .env, secretos CI/CD, claves cloud, logs redactados y límites seguros en Claude Code.

Gestión de secretos con Claude Code: de .env a la rotación en producción

Las API keys, las URL de base de datos, los OAuth client secrets y las credenciales de despliegue en la nube son necesarios para cualquier aplicación real. También son los valores que, si se copian sin cuidado, acaban viviendo en el historial de Git, logs de CI, capturas, tickets, README y borradores de artículos. Cuando usas Claude Code para depurar, migrar, desplegar o documentar, la regla inicial debe ser clara: Claude Code puede ayudarte a construir el sistema seguro, pero no debe ver, imprimir, guardar ni reutilizar secretos reales.

Gestionar secretos no es solo meter contraseñas en una caja fuerte. Es separar configuración y código, aislar local, desarrollo, staging y producción, aplicar mínimos privilegios, validar la configuración al arrancar, redactar logs y tener un proceso de rotación antes de que haya un incidente. El principio de configuración de The Twelve-Factor App sigue siendo una buena base: la configuración debe venir del entorno, no estar hardcodeada en el repositorio. En la práctica necesitas también .gitignore, .env.example, un loader con validación, CI/CD secrets, un secret store cloud y una checklist de rotación.

flowchart LR
  Dev["Local .env"] --> Loader["Validated config loader"]
  CI["CI/CD secrets"] --> Deploy["Deployment runtime"]
  Store["AWS / GCP / Azure secret store"] --> Deploy
  Deploy --> App["Application process"]
  App --> Logs["Redacted logs"]

1. Decide qué va en cada lugar

El error de principiante es tratar todas las variables de entorno igual. Una prueba práctica: si al filtrarse un valor alguien puede gastar dinero, enviar email, leer datos, escribir datos, desplegar código o suplantar a un usuario, trátalo como secreto. Una URL pública, el nombre de una feature flag o un OAuth client ID suelen tener menor sensibilidad porque por sí solos no conceden permisos.

Caso de usoEjemplosDesarrollo localProducción
Email e integraciones APISendGrid API key, Stripe secret key, GitHub tokenUsa claves sandbox o test en .envInyecta desde CI/CD secrets o secret store
Base de datosDATABASE_URL, usuario, contraseñaUsuario local o solo devSepara lectura/escritura y rota contraseñas
Despliegue cloudCredenciales AWS/GCP/AzureEvita claves locales de larga vidaUsa OIDC o rol solo de despliegue
OAuth y webhooksOAUTH_CLIENT_SECRET, webhook signing secretApp local separadaSecretos prod fuera del repo

La separación por entorno es lo importante. No reutilices la key de producción de Stripe en local. No pongas en CI un GitHub token personal con acceso amplio a la organización. No des permisos de administrador a una credencial que solo despliega. Eso es mínimo privilegio: el alcance justo, en el entorno correcto y, si es posible, con duración limitada.

2. Committea la forma, nunca el valor

.env es cómodo para trabajar en local, pero no debe entrar en Git. El repositorio debe contener .env.example, con nombres de variables, formato, origen y propósito. Para onboarding, combínalo con la guía de gestión de variables de entorno y reducirás preguntas repetidas.

# Local secrets
.env
.env.*
!.env.example
!.env.test.example

# Logs and generated output that may contain tokens
npm-debug.log*
yarn-debug.log*
coverage/
dist/
# .env.example - placeholders only, never real values
NODE_ENV=development
APP_BASE_URL=http://localhost:3000

# Use a local database user, not production credentials.
DATABASE_URL=postgres://app_user:replace-me@localhost:5432/app_dev

# Use test/sandbox keys for local development.
SENDGRID_API_KEY=SG.xxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxx
GITHUB_TOKEN=ghp_xxxxxx

# OAuth secrets must be separated by environment.
OAUTH_CLIENT_ID=local-client-id
OAUTH_CLIENT_SECRET=replace-me

# Deployment reads these from CI or a cloud secret store.
AWS_REGION=ap-northeast-1
DEPLOY_ROLE_ARN=arn:aws:iam::123456789012:role/app-deploy-dev

Cuando pidas ayuda a Claude Code, define el límite: puede leer .env.example, manifests de despliegue, scripts de package y nombres de variables; no puede abrir .env, copiar valores reales al chat ni escribir credenciales en docs. Si una implementación necesita un valor real, lo configuras tú en local, CI o el secret store, y Claude Code solo recibe el nombre de la variable.

3. Valida al arrancar y redacta los logs

Una app debe fallar rápido si falta un secreto o si tiene formato inválido. También debe dificultar que alguien imprima un token durante una sesión de debug. Este loader de Node.js usa dotenv y envalid para validar el entorno y ofrece redactConfig para logs, health checks y soporte.

import { config as loadDotenv } from "dotenv";
import { cleanEnv, str, url } from "envalid";

const envFile = process.env.NODE_ENV === "test" ? ".env.test" : ".env";
loadDotenv({ path: envFile });

const secretKeyPattern = /(KEY|TOKEN|SECRET|PASSWORD|DATABASE_URL|PRIVATE)/i;

const env = cleanEnv(process.env, {
  NODE_ENV: str({
    choices: ["development", "test", "staging", "production"],
    default: "development",
  }),
  APP_BASE_URL: url({ default: "http://localhost:3000" }),
  DATABASE_URL: url(),
  SENDGRID_API_KEY: str(),
  STRIPE_SECRET_KEY: str(),
  GITHUB_TOKEN: str(),
  OAUTH_CLIENT_ID: str(),
  OAUTH_CLIENT_SECRET: str(),
  AWS_REGION: str({ default: "ap-northeast-1" }),
  DEPLOY_ROLE_ARN: str(),
});

export function appConfig() {
  return Object.freeze({
    nodeEnv: env.NODE_ENV,
    appBaseUrl: env.APP_BASE_URL,
    databaseUrl: env.DATABASE_URL,
    sendgridApiKey: env.SENDGRID_API_KEY,
    stripeSecretKey: env.STRIPE_SECRET_KEY,
    githubToken: env.GITHUB_TOKEN,
    oauthClientId: env.OAUTH_CLIENT_ID,
    oauthClientSecret: env.OAUTH_CLIENT_SECRET,
    awsRegion: env.AWS_REGION,
    deployRoleArn: env.DEPLOY_ROLE_ARN,
  });
}

export function redactValue(key, value) {
  if (!secretKeyPattern.test(key)) return value;
  if (!value) return "<empty>";
  const text = String(value);
  if (text.length <= 8) return "<redacted>";
  return `${text.slice(0, 4)}...${text.slice(-4)}`;
}

export function redactConfig(config) {
  return Object.fromEntries(
    Object.entries(config).map(([key, value]) => [key, redactValue(key, value)]),
  );
}

if (process.argv[1] === new URL(import.meta.url).pathname) {
  console.log(redactConfig(appConfig()));
}

Un fallo típico es añadir console.log(process.env) en una incidencia nocturna y pegar el log de CI en un ticket o en Slack. Si luego pides a Claude Code que resuma esos logs crudos, puede volver a insertar secretos en tests, documentación o un artículo. Primero redacta, después pregunta. Las capturas también deben recortarse o difuminarse antes de subirlas.

4. Dale límites explícitos a Claude Code

Claude Code casi nunca necesita el valor real. Necesita nombres, formatos, errores ya redactados y la finalidad de cada permiso. Copia este bloque al inicio de tareas de seguridad, despliegue o depuración.

You may inspect .env.example, package.json, deployment manifests, and secret names.
Do not open, print, summarize, store, or copy .env, CI/CD secret values, cloud credentials, production dumps, or screenshots containing tokens.
When you need a value, ask me to set it outside chat and confirm only the variable name.
If a secret appears in command output, stop, redact it, and report which file or command exposed it.
Before changing permissions, explain the least-privilege scope and ask for approval.
Do not paste real secrets into prompts, logs, documentation, code comments, tests, tickets, or articles.

También limita comandos. printenv, cat .env, CLI cloud que muestran credenciales, dumps completos de logs de CI y capturas deben requerir confirmación. Con .env.example, tipos, errores redactados y documentación oficial, Claude Code puede resolver la mayoría de cambios sin tocar valores reales.

5. Usa CI/CD secrets y secret stores con intención

Una separación práctica es .env para local, CI/CD secrets para pipelines y un secret store cloud para runtime de producción. En AWS usa AWS Secrets Manager. En Google Cloud, Secret Manager. En Azure, Key Vault. En GitHub activa secret scanning para detectar tokens filtrados cuanto antes.

name: deploy

on:
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    env:
      NODE_ENV: production
      AWS_REGION: ap-northeast-1
    steps:
      - uses: actions/checkout@v4
      - name: Validate required secret names
        run: test -n "${{ secrets.DEPLOY_ROLE_ARN }}" && test -n "${{ secrets.DATABASE_URL }}"
      - name: Deploy without echoing secrets
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          DEPLOY_ROLE_ARN: ${{ secrets.DEPLOY_ROLE_ARN }}
        run: npm run deploy

La trampa de CI es “hagamos echo para ver qué pasa”. GitHub Actions enmascara muchos secretos exactos, pero no siempre protege valores derivados, URLs codificadas, JSON, capturas o valores que no se registraron como secret. Pide a Claude Code nombres de variables y pasos de validación, no valores. Si propone permisos amplios, exige una razón y reduce el alcance.

6. Rota antes de que sea obligatorio

La rotación debe ser mantenimiento normal, no solo respuesta a incidentes. SendGrid, Stripe, GitHub tokens, contraseñas de base de datos, OAuth client secrets, webhook signing secrets y políticas de confianza cloud necesitan owner, entorno, consumidores, fecha de última rotación y próxima revisión.

## Secret rotation checklist
- [ ] Identify owner, environment, consumers, and business impact.
- [ ] Create a new secret with the smallest required scope.
- [ ] Store it in CI/CD secrets or the cloud secret store.
- [ ] Deploy one service or job with the new value.
- [ ] Confirm logs and metrics without printing the secret.
- [ ] Revoke the old secret.
- [ ] Scan Git history, tickets, docs, screenshots, and chat snippets.
- [ ] Record the rotation date and next review date.

Claude Code es útil para convertir esto en un issue template, runbook o plan de migración. No le pases el secreto antiguo ni el nuevo. Pídele algo como: “Encuentra todas las referencias a SENDGRID_API_KEY y prepara un plan seguro para cambiar a la key v2”.

7. Revisa los fallos antes de publicar

Detén la publicación o el despliegue si ocurre algo de esto:

  • .env o .env.production fue committeado y la key expuesta no se revocó.
  • Capturas, logs de CI, reportes de error o ejemplos de artículos contienen tokens, URLs de DB u OAuth secrets.
  • Una clave cloud tiene permisos de administrador cuando bastaría con desplegar.
  • Credenciales de producción de Stripe, SendGrid, base de datos o GitHub se usan en local.
  • OAuth client secrets o webhook signing secrets no tienen owner ni runbook de rotación.
  • Un asistente de IA recibió valores reales y luego los reutilizó en README, tests, tickets o borradores.

Los incidentes de seguridad suelen venir de huecos de proceso. Usa la checklist de auditoría de seguridad, revisa la guía de fallos de seguridad, conecta esto con la guía de desarrollo API y, si usas SendGrid o correo transaccional, consulta el artículo de automatización de email.

8. Implantación realista en equipo

No empieces migrando todos los servicios a un secret store en una semana. Elige una app y completa el camino: .gitignore, .env.example, loader validado, logs redactados, CI/CD secrets, secret store de producción y registro de rotación. Después migra los tipos recurrentes: SendGrid, Stripe, GitHub token, DATABASE_URL, OAuth client secret y credenciales de despliegue.

En las formaciones y consultorías de ClaudeCodeLab trabajamos con la forma real de tu repositorio, pero sin recibir secretos reales. Definimos qué puede inspeccionar Claude Code, diseñamos límites de CI/CD secrets, activamos GitHub secret scanning, planificamos AWS/GCP/Azure secret stores y dejamos prompts y runbooks reutilizables. Así el equipo puede aplicarlo en code review al día siguiente.

En resumen: gestionar secretos no es solo esconder cadenas. Es separar valores del código, aislar entornos, validar al arrancar, redactar logs, reducir permisos y practicar la rotación. Claude Code puede construir y revisar ese sistema, pero no debe convertirse en otro lugar donde se copian secretos.

Al probar este flujo en la app Node.js de ejemplo de Masa, el loader detectó valores faltantes, redactConfig evitó que la URL de base de datos y las API keys aparecieran en CI, y el workflow de deploy ya no necesitó permisos amplios de escritura. La sorpresa fue una captura antigua con una Stripe test key visible, así que se reemitió antes de publicar. La lección práctica: revisa logs, imágenes y borradores con la misma sospecha que el código fuente.

#claude-code #security #gestion-de-secretos #devops
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.