7 fallos de seguridad con Claude Code: causas, recuperación y prevención
Evita fugas de .env, daños en producción, costes de CI y prompt injection al usar Claude Code.
Claude Code no es solo un chat que sugiere código. Puede editar archivos, ejecutar pruebas, leer el estado de Git y proponer comandos de despliegue. Esa capacidad ahorra tiempo, pero también hace que una aprobación distraída ejecute una acción peligrosa más rápido que si la escribieras a mano.
Esta guía convierte los accidentes de seguridad más comunes en una lista práctica de defensas. Para principiantes: un permiso es el límite de lo que el agente puede hacer, un hook es un punto de control antes o después de usar una herramienta, y un sandbox es un espacio aislado donde un error tiene menos impacto. Los ejemplos incluyen settings.json, un scanner de secretos en Node.js y un workflow de GitHub Actions.
flowchart TD
Request["User request"] --> Plan["Claude Code plan"]
Plan --> Permission["Permission rules"]
Permission --> Hook["PreToolUse hook"]
Hook --> Execute["Tool execution"]
Execute --> Audit["Log, review, recovery"]
Hook -->|block risky command| Stop["Stop before damage"]
Mapa de fallos
| Caso de fallo | Cuándo ocurre | Daño | Barrera inicial |
|---|---|---|---|
Confirmar .env | ”Añádelo también para CI” | Fuga de claves y gasto no deseado | .gitignore y scanner de staged files |
| Borrar datos de producción | Una migración apunta al URL equivocado | Pérdida de datos | Verificación de entorno antes de DB |
git push --force | Resolver conflictos con prisa | Pérdida de commits del equipo | Reglas ask y protección de ramas |
| Review de IA en bucle | Cada PR lanza automatización amplia | Coste de Actions y API | max-turns, timeout, mínimo privilegio |
| Pegar logs no confiables | El log trae instrucciones ocultas | Prompt injection | Denegar fetch web y shell arriesgado |
| MCP demasiado amplio | Se confía rápido en un servidor externo | Lectura excesiva de datos locales | Permitir solo MCP confiables |
| Fatiga de aprobación | Se pulsa aceptar sin leer | Comandos peligrosos aprobados | Hooks que bloquean por defecto |
El mensaje no es que Claude Code sea inseguro por defecto. La documentación oficial de Security describe permisos orientados a lectura, confirmaciones, sandboxing y responsabilidad del usuario. El riesgo real aparece cuando el proceso del equipo se relaja. La configuración debe hacer fácil el camino seguro y difícil el camino peligroso.
Caso práctico 1: evitar fugas de API keys en proyectos personales
El error más común es tratar .env como si fuera una caja fuerte. No lo es: es un archivo de texto local. Solo es relativamente seguro mientras no entre en Git, logs, capturas de pantalla o prompts. Si una clave de Stripe, SendGrid, Anthropic o GitHub aparece en un repositorio público, se debe considerar comprometida.
Confirma solo la forma de la configuración, no los valores reales.
# .gitignore
.env
.env.*
!.env.example
secrets/
*.pem
*.key
*service-account*.json
credentials.json
# .env.example
ANTHROPIC_API_KEY=replace_me
DATABASE_URL=postgres://app_user:password@localhost:5432/app_dev
STRIPE_SECRET_KEY=sk_test_replace_me
Después ajusta los permisos de Claude Code. deny bloquea, ask pide confirmación y allow aprueba comandos seguros y repetitivos. Las páginas oficiales de Settings y Configure permissions explican la evaluación de estas reglas.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Bash(git status)",
"Bash(git diff *)"
],
"ask": [
"Bash(git push *)",
"Bash(npm run deploy *)",
"Write(./migrations/**)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(rm -rf *)",
"Bash(curl *)",
"Bash(wget *)",
"WebFetch"
]
}
}
Esta configuración no desactiva Claude Code. Hace fluidos los comandos de bajo riesgo y vuelve explícitas las acciones destructivas. Si tu proyecto necesita acceso web, empieza con reglas estrechas: define el dominio, el propósito y la revisión humana antes de relajar permisos.
Caso práctico 2: mantener honestas las revisiones de PR
En equipos, el fallo peligroso suele ser de proceso. La gente empieza a asumir que “la IA lo revisó” significa que nadie debe mirar archivos de permisos, workflows o manejo de credenciales. Justo ahí se filtran los problemas.
Añade un scanner sin dependencias externas. Por defecto revisa archivos staged; en CI puede revisar todo el repositorio con --all.
// scripts/claude-security-check.mjs
import { execFileSync } from "node:child_process";
import fs from "node:fs";
const args = process.argv.slice(2);
const scanAll = args.includes("--all");
const explicitFiles = args.filter((arg) => arg !== "--all");
function runGit(args) {
return execFileSync("git", args, { encoding: "utf8", maxBuffer: 10 * 1024 * 1024 });
}
function filesToScan() {
if (explicitFiles.length > 0) return explicitFiles;
if (scanAll) return runGit(["ls-files"]).split(/\r?\n/).filter(Boolean);
return runGit(["diff", "--cached", "--name-only"]).split(/\r?\n/).filter(Boolean);
}
function readTrackedOrWorkingTree(file) {
if (scanAll || explicitFiles.length > 0) return fs.readFileSync(file, "utf8");
return runGit(["show", `:${file}`]);
}
const forbiddenPath = [
/^\.env$/,
/^\.env\./,
/(^|\/)secrets\//,
/(^|\/).*service-account.*\.json$/i,
/(^|\/)credentials\.json$/i,
/\.(pem|key)$/i
];
const secretPattern =
/(sk-ant-[A-Za-z0-9_-]{20,}|sk_live_[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----)/;
let failed = false;
for (const file of filesToScan()) {
if (forbiddenPath.some((pattern) => pattern.test(file))) {
console.error(`[blocked] forbidden secret path: ${file}`);
failed = true;
continue;
}
try {
const text = readTrackedOrWorkingTree(file);
if (secretPattern.test(text)) {
console.error(`[blocked] secret-like value found in: ${file}`);
failed = true;
}
} catch {
// Ignore deleted or binary files.
}
}
if (failed) process.exit(1);
console.log("security check passed");
{
"scripts": {
"security:staged": "node scripts/claude-security-check.mjs",
"security:all": "node scripts/claude-security-check.mjs --all"
}
}
El tropiezo habitual es quedarse en “tenemos un script”. Incluye npm run security:staged en la rutina de commit, la plantilla de PR o CI. Pedirle a Claude Code que recuerde ejecutar la comprobación es más débil que una orden que falla automáticamente.
Caso práctico 3: proteger producción y el presupuesto de CI
Los incidentes de producción suelen nacer de confundir entornos. El problema no es solo DROP TABLE; es ejecutarlo contra DATABASE_URL de producción pensando que era desarrollo. Antes de pedir a Claude Code que borre datos antiguos, muestra en texto claro la etiqueta de base de datos, proyecto cloud, rama y hora del backup.
Para GitHub Actions, la documentación oficial de Claude Code GitHub Actions recomienda usar Secrets para claves API y limitar permisos a lo necesario. Este workflow revisa el diff de un PR sin permiso de escritura al repositorio.
name: Claude Code guarded review
"on":
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
claude-security-review:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run repository secret scan
run: node scripts/claude-security-check.mjs --all
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: "${{ secrets.ANTHROPIC_API_KEY }}"
prompt: >
Review only the pull request diff for secret handling, auth checks,
destructive commands, and permission changes. Do not modify files.
claude_args: |
--max-turns 3
--disallowedTools "Bash(git push *)" "Bash(npm run deploy *)" "Bash(rm -rf *)"
permissions: contents: read importa porque un job solo de review no necesita escritura. timeout-minutes y --max-turns también son controles de seguridad: la automatización sin límites puede causar incidentes de coste y disponibilidad.
Recuperación si el accidente ya ocurrió
Si se filtró una API key, no empieces limpiando la historia de Git. Primero revoca o rota la clave en el proveedor. Un repositorio limpio no sirve si alguien ya copió el valor.
- Revoca o rota la clave expuesta.
- Revisa logs de uso y facturación durante la ventana de exposición.
- Sustituye GitHub Secrets, variables de despliegue y valores de CI.
- Elimina el valor del historial de Git y pide limpieza de caché si hace falta.
- Añade
.gitignore, permisos y scanner en el mismo PR de remediación.
Si se dañaron datos de producción, pausa escrituras o cambia la app a modo solo lectura antes de pedir una corrección. Decide primero el backup, el destino de restauración y la pérdida aceptable. Los comandos de recuperación deben ejecutarse uno por uno, con confirmación humana y logs.
Documentación, enlaces internos y siguiente paso
Usa las páginas oficiales de Security, Configure permissions, Settings, Hooks y GitHub Actions como referencia principal. Hooks es especialmente útil porque permite comprobar antes de ejecutar herramientas.
Para ampliar dentro del sitio, lee /es/blog/claude-code-security-best-practices/, /es/blog/claude-code-permissions-guide/ y /es/blog/claude-code-secrets-management/.
Si necesitas plantillas listas para adaptar, revisa los materiales de /products/. Para convertir esto en un plan de adopción, política de CI y flujo de review de equipo, usa las opciones de consulta y formación de /training/.
En el repositorio local de prueba de Masa, esta configuración bloqueó un .env staged por error, una cadena falsa sk_live_ y un job de GitHub Actions con permisos demasiado amplios antes de publicar. El scanner por regex no captura todos los formatos de secreto, así que la respuesta duradera es por capas: rotación en el proveedor, mínimo privilegio, comprobaciones automáticas y revisión humana antes de aprobar acciones de Claude Code.
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
Escalera de permisos de Claude Code para ampliar acceso sin perder control
Pasa de read-only a ediciones limitadas, comandos de prueba y checks de deploy con menos riesgo.
Claude Code Small PR Proof Pack: cambios pequeños que sí se pueden revisar
Un paquete de prueba para PRs de Claude Code: diff, checks, URL pública, CTA y rollback.
Gate de revisión antes del commit con Claude Code
Cómo revisar con Claude Code antes del commit: diff, build, URL pública, Gumroad, consultoría, tests y archivos ajenos.