Guía Completa de Seguridad para Claude Code: Claves API, Permisos y Protección en Producción
Seguridad práctica de Claude Code: claves API, permisos, secretos, escaneo antes del commit y protección de producción.
Claude Code tiene potentes capacidades de manipulación de archivos y ejecución de comandos — pero una mala configuración puede provocar accidentes irreversibles. Hacer commit de un archivo .env, borrar accidentalmente una base de datos de producción, imprimir una clave API en los logs — estos son incidentes reales causados por usar Claude Code sin las protecciones adecuadas.
Este artículo ofrece una explicación a nivel de implementación de las mejores prácticas de seguridad para Claude Code. El enfoque está en configuraciones listas para usar y código preventivo que puedes copiar y aplicar de inmediato.
Por qué Claude Code necesita medidas de seguridad
A diferencia de un editor de texto normal, Claude Code tiene las siguientes capacidades:
- Leer, escribir y eliminar cualquier archivo (
Read/Write/Edit/Bash(rm)) - Ejecutar comandos de shell (
Bash) - Acceso a la red (
WebFetch/ llamadas API) - Publicar en servicios externos (GitHub, Slack, etc.)
Todo esto puede ejecutarse con la aprobación del usuario. El problema es que aprobar mecánicamente cada prompt permite que operaciones no deseadas se cuelen. Las medidas de seguridad consisten en eliminar estructuralmente el margen de error.
Medida 1: Gestión de claves API — .env + .gitignore como base
Lo que NO debes hacer
// ❌ Escrito directamente en el código fuente
const client = new Anthropic({ apiKey: "PASTE_REAL_API_KEY_HERE" });
// ❌ Escrito en CLAUDE.md o archivos de configuración
// ANTHROPIC_API_KEY=PASTE_REAL_API_KEY_HERE
// ❌ Incluido en el prompt de claude -p
// Usa QIITA_TOKEN=PASTE_REAL_TOKEN_HERE para publicar
El enfoque correcto
# .env (excluido de git, almacenado solo en la máquina local)
ANTHROPIC_API_KEY=<anthropic-api-key>
QIITA_TOKEN=<qiita-token>
SLACK_BOT_TOKEN=<slack-bot-token>
DATABASE_URL=postgresql://...
# Siempre añadir a .gitignore
.env
.env.*
.env.local
!.env.example # ← El archivo de ejemplo sí puede commitearse
*.pem
*.key
credentials.json
*-service-account.json
# .env.example (seguro de commitear, valores vacíos)
ANTHROPIC_API_KEY=
QIITA_TOKEN=
SLACK_BOT_TOKEN=
DATABASE_URL=
Leer variables en el código
// ✅ Leer desde variables de entorno
import { config } from "dotenv";
config();
const token = process.env.QIITA_TOKEN;
if (!token) throw new Error("QIITA_TOKEN no está configurado. Por favor, revisa tu archivo .env.");
Documentar prohibiciones en CLAUDE.md
## Prohibiciones de Seguridad
- Nunca incluir claves API o tokens en prompts
- Nunca leer y mostrar el contenido de archivos .env
- Nunca escribir valores de variables de entorno en logs o comentarios
- Nunca usar console.log con el contenido de process.env
Medida 2: Escaneo de secretos antes del commit
Incluso con .env en .gitignore, pueden ocurrir entradas accidentales en otros archivos o errores de copia-pega. Añade un escaneo automático pre-commit.
Verificación pre-commit con Hooks
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit*)",
"hooks": [
{
"type": "command",
"command": "node scripts/secret-scan.mjs"
}
]
}
]
}
}
scripts/secret-scan.mjs:
import { execSync } from "child_process";
// Obtener cambios en staging
const diff = execSync("git diff --cached").toString();
const PATTERNS = [
{ name: "Asignación de clave API de Anthropic", re: /\b(?:ANTHROPIC_API_KEY|CLAUDE_API_KEY)\s*[:=]\s*["']?[^"'\s]{20,}/i },
{ name: "Asignación de clave API de OpenAI", re: /\bOPENAI_API_KEY\s*[:=]\s*["']?[^"'\s]{20,}/i },
{ name: "Clave de acceso AWS", re: /\bAKIA[0-9A-Z]{16}\b/ },
{ name: "Token de Slack", re: /\bxox[baprs]-[0-9A-Za-z-]{10,}\b/ },
{ name: "Secreto genérico", re: /\b(?:secret|token|api[_-]?key|password)\s*[:=]\s*["'][^"']{10,}["']/i },
];
const found = PATTERNS.filter(({ re }) => re.test(diff));
if (found.length > 0) {
console.error("🚨 ¡Secreto detectado! Abortando el commit:");
found.forEach(({ name }) => console.error(` - ${name}`));
console.error("\nSolución: ejecuta `git reset HEAD <archivo>` para retirar el archivo del staging");
process.exit(1); // Código de salida 1 → El Hook bloquea el comando
}
console.log("✓ Escaneo de secretos: sin problemas encontrados");
process.exit(0);
Esto significa que en el momento en que Claude Code intenta ejecutar git commit, se lanza automáticamente un escaneo y cualquier filtración detectada queda bloqueada.
Medida 3: Configuración de modos de permisos
La configuración de permitir/denegar de Claude Code puede controlarse de forma detallada a nivel de archivo.
Configuración de permisos en .claude/settings.json
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "default",
"disableBypassPermissionsMode": "disable",
"allow": [
"Read(**)",
"Glob(**)",
"Grep(**)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(rm -rf*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(DROP TABLE*)",
"Bash(truncate*)",
"Bash(curl * | bash)",
"Bash(wget * | sh)"
],
"ask": [
"Write(**)",
"Edit(**)",
"Bash(git commit*)",
"Bash(git push*)",
"Bash(npm publish*)",
"Bash(wrangler pages deploy*)"
]
},
"disableAutoMode": "disable"
}
| Configuración | Significado |
|---|---|
allow | Ejecutar sin confirmación |
deny | Nunca ejecutar (bloqueado completamente) |
ask | Requiere aprobación cada vez |
Principio clave: Los comandos destructivos van en deny, las operaciones de escritura en ask, las operaciones de lectura en allow.
Separa producción y política de organización con local o managed settings
El modelo oficial de configuración aplica los scopes en este orden: managed, argumentos de línea de comandos, local, project y user. En lugar de depender de un cambio por archivo personalizado no oficial, usa .claude/settings.local.json para un terminal personal más estricto de producción y managed settings para reglas de organización.
Usa .claude/settings.local.json para overrides locales y no lo subas a git.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "plan",
"disableBypassPermissionsMode": "disable",
"allow": ["Read(**)", "Glob(**)", "Grep(**)", "Bash(git log*)", "Bash(git diff*)"],
"deny": ["Write(**)", "Edit(**)", "Bash(git push*)", "Bash(rm*)", "Bash(*deploy*)"],
"ask": []
},
"disableAutoMode": "disable"
}
Para una política de equipo o empresa, coloca el límite en managed settings. Con allowManagedPermissionRulesOnly, usuarios y repositorios de proyecto no pueden redefinir reglas allow, ask o deny para rodear la política de la organización.
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)"
],
"disableBypassPermissionsMode": "disable"
},
"disableAutoMode": "disable",
"allowManagedPermissionRulesOnly": true
}
Medida 4: Protección del entorno de producción
Separar explícitamente los destinos de conexión
## CLAUDE.md — Reglas del entorno de producción
## Detección de entorno
- Si DATABASE_URL contiene 'prod' o 'production', es un **entorno de producción**
- En producción, nunca ejecutar:
- DROP / TRUNCATE / DELETE (sin cláusula WHERE)
- Migraciones (requieren confirmación previa)
- Eliminaciones masivas de archivos
## Flujo de confirmación
Todos los cambios en producción deben:
1. Probarse primero en un entorno de staging
2. Recibir confirmación del usuario
3. Reportar resultados tras la ejecución
Controlar conexiones con variables de entorno
// scripts/db-query.mjs
const env = process.env.NODE_ENV ?? "development";
const dbUrl = process.env.DATABASE_URL;
if (env === "production" && process.argv.includes("--write")) {
console.error("❌ Escribir en producción requiere el flag --force-production");
process.exit(1);
}
Medida 5: Protecciones para operaciones de archivos
Automatizar copias de seguridad antes de eliminar
// Hooks en .claude/settings.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(rm *)",
"hooks": [
{
"type": "command",
"command": "echo '⚠️ Un comando de eliminación está a punto de ejecutarse. Presiona Ctrl+C para cancelar.' && sleep 3"
}
]
}
]
}
}
Proteger archivos críticos de ediciones accidentales
## CLAUDE.md — Archivos que no deben modificarse
Los siguientes archivos **nunca deben editarse**:
- .env (contiene variables de entorno y claves secretas)
- wrangler.toml (configuración de producción de Cloudflare)
- scripts/deploy.sh (script de despliegue)
- .github/workflows/*.yml (configuración de CI/CD)
Si se necesitan cambios, consultar primero con el usuario.
5 errores comunes
1. Añadir .gitignore después del hecho es demasiado tarde
Un archivo .env ya commiteado permanece en el historial de git aunque se añada más tarde a .gitignore.
# Eliminación completa del historial (atención: requiere force push)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Alternativamente, usar BFG Repo Cleaner
Si el archivo ya se subió a GitHub, siempre rota tus claves API primero antes de limpiar el historial.
2. Almacenar archivos JSON de cuentas de servicio en el repositorio
Las claves de cuentas de servicio de Google Cloud o AWS suelen distribuirse como archivos .json, pero almacenarlos en un repositorio es peligroso. Conviértelos en variables de entorno o migra a un Secret Manager (AWS Secrets Manager / GCP Secret Manager).
3. Ejecutar comandos interactivos con la herramienta Bash
Durante la ejecución sin cabeza con claude -p, los comandos que requieren entrada interactiva como sudo o vim harán que el proceso se cuelgue. Usa solo comandos no interactivos.
4. Incluir credenciales en mensajes de error
// ❌ Peligroso: la clave API aparece en los logs
throw new Error(`Autenticación fallida: token=${process.env.TOKEN}`);
// ✅ Seguro: no exponer el valor
throw new Error(`Autenticación fallida: por favor revisa la variable de entorno TOKEN`);
5. Reutilizar la misma configuración de permisos en todos los proyectos
Usar el mismo settings.json para proyectos personales y de trabajo significa que la configuración laxa del proyecto personal puede sobrescribir los requisitos más estrictos del proyecto de trabajo. Gestiona .claude/settings.json por separado para cada proyecto.
Reglas operativas prácticas
No exponer secretos durante el trabajo normal
Cuando pides a Claude Code “arregla este error”, no pegues el log completo ni el contenido de .env. Define antes que las claves API, tokens OAuth, cookies, URLs de base de datos, correos de clientes, IDs de facturación y claves privadas nunca se copian en prompts, issues o chats.
Si Claude Code necesita contexto, redacta los valores y conserva solo la forma de la configuración. DATABASE_URL=***REDACTED*** basta para indicar que existe una URL de base de datos. El valor real casi nunca es necesario para depurar código de aplicación.
| Seguro de entregar | No entregar |
|---|---|
| Tipo de error, archivos del stack trace, pasos de reproducción | Claves API, claves privadas, session cookies, valores reales de .env |
.env.example, nombres de settings, reglas de permisos, comando fallido | URLs de base de datos de producción, datos de clientes, credenciales internas |
| Logs redactados, datos de prueba, valores locales de ejemplo | Tokens reales, JSON de service account, capturas con secretos |
Incluye esta tabla en CLAUDE.md para que cada sesión empiece con el mismo límite. En equipos, “no exponer secretos” debe ser una regla operativa, no conocimiento informal.
Duplicar el escaneo de secretos antes del commit
El Hook PreToolUse anterior bloquea el commit cuando Claude Code es quien ejecuta git commit. No cubre a una persona que hace commit desde otra terminal ni archivos generados en CI. En equipos de producción, usa tres capas: Hook de Claude Code, pre-commit local y secret scan en CI que bloquee el merge.
La configuración mínima útil es bloquear localmente, revisar de nuevo en CI y fallar el pull request si aparece un patrón de secreto. Herramientas como gitleaks o trufflehog son mejores para detección a escala de CI; el script de este artículo funciona bien como guardia local rápido.
Ejemplos concretos de fallo
Fallo 1: leer .env durante una investigación
Un desarrollador pidió a Claude Code “revisa las variables de entorno” y los valores reales quedaron en la conversación o en logs de trabajo. La corrección es denegar la lectura de .env y entregar solo .env.example.
Fallo 2: pegar un token de publicación de Qiita en el prompt
Una tarea de automatización incluyó QIITA_TOKEN directamente en el prompt, con riesgo de persistirlo en un subagente o log. El flujo seguro es guardar el token en .env y hacer que el comando solo use el nombre de la variable de entorno.
Fallo 3: URLs de producción y staging muy parecidas
La instrucción decía solo “limpia la base de datos” y omitía la verificación de conexión. Si la URL activa era producción, un delete o una migración podía convertirse en incidente. Antes de escribir, muestra NODE_ENV, host y nombre de base de datos, y exige confirmación explícita.
Primeros pasos tras un incidente
Si sospechas que se filtró un secreto, el primer paso no es limpiar el historial. Es desactivar la credencial.
- Rota o revoca de inmediato la clave API, token o contraseña afectada
- Revisa logs de GitHub Actions, Cloudflare, AWS, GCP y SaaS conectados
- Registra quién expuso qué, cuándo, en qué repositorio y por qué canal
- Elimina el secreto del historial de git y logs, y comunica el impacto de cualquier force push
- Endurece reglas
deny, Hooks, escaneos CI y prohibiciones enCLAUDE.md
En la práctica, detener primero la credencial y limpiar después el historial reduce errores. Durante un incidente la gente suele pegar más logs para ayudar, así que prepara una plantilla de logs redactados antes de necesitarla.
Ruta natural hacia material y consultoría
La seguridad de Claude Code no se resuelve con un solo archivo de settings. También hay que revisar estructura del repositorio, CI, permisos de despliegue y flujo de aprobación del equipo.
En ClaudeCodeLab, la ruta de aprendizaje individual empieza por higiene de .env y permission rules. En consultoría para equipos, las primeras preguntas son dónde forzar managed settings y dónde debe bloquear merges el secret scan de CI. Si ya usas Claude Code en el trabajo, empieza mapeando quién puede acceder a qué secretos antes de ajustar permisos finos.
Lista de verificación de seguridad
Una lista de verificación para configurar un proyecto de Claude Code:
### Configuración básica
- [ ] .env creado y añadido a .gitignore
- [ ] .env.example creado y compartido con el equipo
- [ ] Verificado mediante git log que los commits existentes no contienen secretos
### Configuración de permisos
- [ ] Lista de deny configurada en .claude/settings.json
- [ ] Comandos destructivos (rm -rf, DROP TABLE, etc.) añadidos a deny
- [ ] Comandos de despliegue en producción configurados como ask
### Automatización
- [ ] Hook de escaneo de secretos pre-commit configurado
- [ ] Prohibiciones de seguridad documentadas en CLAUDE.md
### Operaciones
- [ ] Calendario de rotación de claves API establecido (recomendado: cada 90 días)
- [ ] Trabajo en producción restringido con .claude/settings.local.json o managed settings
- [ ] Flujo de respuesta a incidentes documentado
Resumen
La seguridad en Claude Code no se trata de “imponer restricciones” — se trata de construir una estructura donde los accidentes no puedan ocurrir.
| Amenaza | Contramedida |
|---|---|
| Filtración de clave API | .env + .gitignore + Hook de escaneo de secretos |
| Eliminación no deseada | Lista de deny + Hook pre-eliminación |
| Errores en producción | local/managed settings + prohibiciones en CLAUDE.md |
| Contaminación de commits | Hook PreToolUse para escaneo pre-commit |
Una vez configurados, estos ajustes son prácticamente libres de mantenimiento. Dedicar 30 minutos hoy puede prevenir un incidente mayor en el futuro.
Artículos relacionados
- Guía de permisos de Claude Code
- Casos de fallos de seguridad en Claude Code
- Guía completa de integración Claude Code + SaaS
- Mejores prácticas de CLAUDE.md
Referencias
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.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Recibo de verificación para Claude Code: build, URL pública, CTA y capturas
Flujo de verificación para cambios de Claude Code con diff, build, URL pública, CTA, capturas y ruta de ingresos.
Permission budget para Claude Code: avanzar seguro sin aprobar cada comando
Diseña un presupuesto de permisos para Claude Code y protege secretos, deploys, billing y datos sin frenar todo.
Mantenimiento de una biblioteca de prompts para Claude Code
Nombra, prueba y reutiliza prompts de Claude Code para convertirlos en una ruta fiable desde PDF gratuito hasta plantillas pagas.