Saltar al contenido

Permisos y Seguridad Operativa

Los 6 modos de permiso, las reglas deny/ask/allow y cómo interactúan entre sí — la primera línea de defensa de un agente con acceso real a tu filesystem.

6 min. de lectura

La pregunta que define este artículo es simple: ¿cuánto confiás en lo que Claude va a hacer sin preguntar? Claude Code separa esa respuesta en dos capas que conviene entender por separado: los modos (comportamiento por defecto) y las reglas (excepciones puntuales).

Los 6 modos de permiso

ModoQué permiteCuándo usarlo
default, mostrado como “Manual” desde v2.1.200Solo lectura sin preguntar; cualquier edición o comando pide aprobaciónTrabajo sensible, repos desconocidos
acceptEditsLee y edita archivos sin interrupcionesEstás iterando sobre código que vos mismo revisás activamente después
planSolo lectura, ni edita ni ejecutaExplorar un codebase nuevo o planificar un refactor antes de tocar nada
autoTodas las acciones, con un clasificador automático que verifica en segundo planoTareas largas donde querés reducir la fatiga de aprobar todo el tiempo
dontAskSolo ejecuta herramientas pre-aprobadas explícitamentePipelines CI/CD y scripts automatizados
bypassPermissionsTodo sin verificacionesÚnicamente en contenedores o VMs aisladas — nunca en tu máquina principal

Cómo se cambia:

# Durante una sesión: Shift+Tab rota entre los modos disponibles.
# bypassPermissions solo entra en el ciclo si arrancaste con
# --dangerously-skip-permissions.

claude --permission-mode plan
claude --permission-mode acceptEdits
claude --permission-mode auto
claude --permission-mode dontAsk               # pensado para CI
claude --permission-mode bypassPermissions     # solo en entornos aislados

Hay dos valores que no se aceptan desde .claude/settings.json ni settings.local.json: auto se ignora, y bypassPermissions hace que la sesión arranque en Manual. Es deliberado: son decisiones de quien lanza la sesión, no de un archivo commiteado en el repo.

Reglas personalizadas: deny → ask → allow

Además de los modos, hay un sistema de reglas granulares por herramienta. Se evalúan en este orden, y gana la primera regla que coincide:

01. ¿Coincide con una regla deny?

Sí → Bloqueado. Punto.No → sigue

02. ¿Coincide con una regla ask?

Sí → Pide confirmaciónNo → sigue

03. ¿Coincide con una regla allow?

Sí → Se ejecuta sin preguntarNo → sigue
Si ninguna regla coincide: comportamiento por defecto del modo activo

deny siempre gana: ni bypassPermissions puede anular un deny de configuración administrada, ni acceptEdits puede levantar un Edit(...) denegado.

Sintaxis: Herramienta o Herramienta(especificador).

{
  "permissions": {
    "allow": [
      "Bash(npm test*)",       // cualquier comando que empiece con "npm test"
      "Bash(docker compose *)",
      "Bash(git log*)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(~/.ssh/*)",
      "WebFetch(domain:vault.miempresa.internal)"
    ]
  }
}

Algunos detalles que conviene tener presentes:

  • El espacio antes de * importa: Bash(ls *) exige un espacio o fin de cadena después de ls (no coincide con lsof); Bash(ls*) sí coincide con ambos. Bash(ls:*) es la sintaxis moderna equivalente a Bash(ls *).
  • Los operadores de shell se evalúan por separado: una regla Bash(comando-seguro *) no habilita comando-seguro && comando-peligroso, porque Claude Code entiende &&, || y ; y evalúa cada subcomando.
  • Read/Edit usan sintaxis estilo .gitignore: //ruta es absoluta desde la raíz del filesystem, ~/ruta desde tu home, /ruta es relativa a la raíz del proyecto (ojo, no del filesystem — /Users/alice/file es relativo al proyecto, no una ruta absoluta real) y ruta o ./ruta es relativa al directorio actual.
  • Límite importante: las reglas deny de Read/Edit bloquean las herramientas internas de Claude, pero no bloquean lo que hagas vía Bash (un cat .env en Bash no lo frena una regla Read(./.env)). Para bloqueo real a nivel de sistema operativo hace falta un sandbox, que combina las reglas deny con su propia lista de dominios permitidos para la red.

Qué agrega cada modo por encima de las reglas

Los modos son el interruptor general; las reglas son el filtro fino. Un ejemplo de cómo interactúan:

  • En plan, aunque tengas Edit(/src/**) en allow, el modo no permite editar nada — es más restrictivo que las reglas permisivas.
  • En auto, al entrar al modo se descartan automáticamente reglas allow peligrosas como Bash(*) o Agent(*), porque darían ejecución arbitraria antes de que el clasificador las evaluara. Las reglas específicas (Bash(npm test)) se mantienen. Al salir, se restauran.
  • En dontAsk, incluso las reglas ask se convierten en denegación — todo lo que no está explícitamente en allow se rechaza. Ideal para CI.

Este es uno de los rincones de Claude Code que más rápido evoluciona. Antes de fijar una política de permisos para todo el equipo, conviene confirmar el comportamiento vigente en la documentación oficial.

Documentación relacionada: sintaxis completa de reglas y referencia de settings.json, donde viven todas estas reglas en disco.

Te sirvió, compartilo

// ¿te sirvió?
// compartilo