Checklist · Intermedio · 15 min
Antes de darle permisos a Claude Code: checklist de seguridad
Diez comprobaciones antes de dar más permisos a Claude Code o abrirlo en un repo ajeno: modos, deny, ask y allow, confianza, sandbox y bypass.
Probado con Claude Code 2.1.316 · revisado
Ver los archivos en GitHub Gratis · licencia MIT
Para qué sirve
Una lista de diez comprobaciones para hacer antes de darle más permisos a Claude Code o de abrirlo en un repositorio que no es tuyo. Ordena lo que dice la documentación oficial: dónde vive cada regla y cuál gana (deny → ask → allow, en cualquier ámbito), qué aplica un proyecto antes y después de aceptar la confianza en la carpeta, por qué auto y bypassPermissions no funcionan desde los ajustes del proyecto, por qué bloquear curl no corta la red y cómo cerrarte la puerta del modo bypass. Cada punto trae su porqué y cómo comprobarlo. Para la sintaxis de las reglas, mira la receta de permisos.
La lista
- Por qué: el modo decide qué se aprueba sin preguntarte. Desde la versión 2.1.283, si tu cuenta y tu modelo lo admiten, las sesiones interactivas en la terminal y en VS Code arrancan en auto: un clasificador aparte revisa en segundo plano los comandos y las peticiones de red y bloquea lo que considera peligroso. Es cómodo, pero no es «sin riesgo»: el clasificador decide por ti. En modo Manual (
default), Claude Code pide permiso la primera vez que usa cada herramienta, salvo un conjunto fijo de comandos de solo lectura (ls,cat,git status…). - Cómo comprobarlo: mira el indicador de modo en la parte inferior de la terminal y cámbialo con
Shift+Tab. Para fijar otro modo inicial, ponpermissions.defaultModeen~/.claude/settings.json, o arranca conclaude --permission-mode default. En un proyecto que no conoces, empieza enplano en Manual. - El orden: el modo inicial sale de la opción
--permission-mode(o--dangerously-skip-permissions), luego dedefaultModeen un archivo de ajustes y por último del valor de fábrica. La extensión de VS Code tiene su propio ajuste,claudeCode.initialPermissionMode, y nunca lee el modo de los ajustes del proyecto.
- Por qué: el modo decide qué se aprueba sin preguntarte. Desde la versión 2.1.283, si tu cuenta y tu modelo lo admiten, las sesiones interactivas en la terminal y en VS Code arrancan en auto: un clasificador aparte revisa en segundo plano los comandos y las peticiones de red y bloquea lo que considera peligroso. Es cómodo, pero no es «sin riesgo»: el clasificador decide por ti. En modo Manual (
- Por qué: una misma regla puede estar en cuatro sitios y sumarse. De mayor a menor prioridad: ajustes administrados de tu organización (no se pueden anular), opciones de la línea de comandos, local (
.claude/settings.local.json, solo tú en este proyecto, fuera de git), proyecto (.claude/settings.json, todo el equipo) y usuario (~/.claude/settings.json, tú en todos los proyectos). Las listas allow, ask y deny no se pisan entre archivos: se juntan. - La regla de oro: las reglas se evalúan en el orden deny → ask → allow y gana la primera que coincide, aunque otra sea más específica. Un deny de cualquier ámbito bloquea aunque otro ámbito lo permita: un deny en tu archivo de usuario gana a un allow del proyecto, y al revés. Un allow no puede abrir una excepción dentro de un deny: con
deny: Bash(aws *), elallow: Bash(aws s3 ls)no sirve. Y un ask pregunta aunque haya un allow más concreto. - Cómo comprobarlo: en la sesión,
/permissionsmuestra cada regla con el archivo de donde viene, y/statusqué archivos de ajustes se cargaron. Pon los deny que quieres en todas partes (tus~/.ssh,~/.aws) en tu archivo de usuario: así ningún repo puede quitártelos.
- Por qué: una misma regla puede estar en cuatro sitios y sumarse. De mayor a menor prioridad: ajustes administrados de tu organización (no se pueden anular), opciones de la línea de comandos, local (
- Por qué: al abrir
claudeen una carpeta nueva aparece el diálogo de confianza. Hasta que lo aceptas, las reglas allow y los additionalDirectories del.claude/settings.jsondel proyecto no se aplican (dan permisos); las deny y ask sí, porque solo restringen. El diálogo lista lo que la carpeta te concedería. Acéptalo solo después de leerlo. - Lo que casi nadie sabe: según la tabla oficial «What runs before you trust a folder», con
claude -po el SDK, en una carpeta en la que nunca confiaste, Claude Code sí usa los hooks de los ajustes del proyecto, el bloqueenv, helpers comoapiKeyHelpery elallowed-toolsde las skills del proyecto, y conecta sin preguntar los servidores de.mcp.json. Lo comprobamos en este PC: un hook SessionStart de un repo de prueba creó un archivo conclaude -pantes incluso de que la CLI dijera «Not logged in». - Cómo comprobarlo: antes de lanzar nada en un repo ajeno, mira
.claude/settings.json,.claude/settings.local.json,.claude/skills/,.claude/agents/y.mcp.json(el scriptrevisar-repo-ajeno.shdel repositorio lo hace sin ejecutar nada). Si vas a usarclaude -pahí, añade--setting-sources user(no lee los ajustes ni el.mcp.jsondel proyecto),--bare(no lee hooks, skills, comandos, subagentes, plugins ni servidores del proyecto; elenvdel proyecto sí se aplica) o--settings '{"disableAllHooks": true}'. Los tres evitaron el hook en nuestra prueba. Ponerlo solo en tus ajustes de usuario no basta: el proyecto tiene más prioridad.
- Por qué: al abrir
# Prueba real: un repo ajeno ejecuta su hook con claude -p (1-nov-2026, Claude Code 2.1.316)
# Repo de prueba con un hook SessionStart en .claude/settings.json que hace touch de un archivo
$ claude -p "di hola" < /dev/null
Ignoring 2 permissions.allow entries from .claude/settings.json: this workspace has not been trusted. ...
Not logged in · Please run /login
$ ls ../HOOK-EJECUTADO
../HOOK-EJECUTADO # el hook se ejecutó: sin confianza y sin sesión iniciada
# Las tres formas de evitarlo (el hook NO se ejecutó en ninguna):
$ claude -p "di hola" --setting-sources user
$ claude -p "di hola" --bare
$ claude -p "di hola" --settings '{"disableAllHooks": true}'
- Por qué: es la causa más común de «Claude me sigue preguntando aunque lo permití en el proyecto». La confianza se guarda por raíz del repositorio git (cubre todo el repo salvo repos anidados, como submódulos, que piden la suya). Si arrancas Claude en tu carpeta personal (home), la confianza dura solo esa sesión y no se guarda. Un
claude -pnunca muestra el diálogo. - Cómo comprobarlo: ejecuta
claude -p "hola"oclaude doctoren la carpeta. Si ves en stderrIgnoring 2 permissions.allow entries from .claude/settings.json: this workspace has not been trusted. Run Claude Code interactively here once and accept the trust dialog, or set projects["…"].hasTrustDialogAccepted: true in …/.claude.json., tus reglas allow del proyecto están en pausa. - Solución: abre
claudeen modo interactivo una vez y acepta. La alternativa de editarhasTrustDialogAccepteda mano en~/.claude.jsonexiste y la documentación la menciona, pero úsala solo en carpetas que ya revisaste. - Otro detalle:
.claude/settings.local.jsonnormalmente se aplica sin confianza porque es tuyo; pero si está versionado en git o.claudees un enlace simbólico, Claude Code lo trata como del repositorio y retiene sus reglas.
- Por qué: es la causa más común de «Claude me sigue preguntando aunque lo permití en el proyecto». La confianza se guarda por raíz del repositorio git (cubre todo el repo salvo repos anidados, como submódulos, que piden la suya). Si arrancas Claude en tu carpeta personal (home), la confianza dura solo esa sesión y no se guarda. Un
- Por qué: para que un repo no pueda decidir por ti cuánto se aprueba solo, Claude Code ignora
defaultMode: "auto"y"bypassPermissions"cuando están en.claude/settings.jsono.claude/settings.local.json. Con auto se usa el valor de fábrica (no eldefaultModede tu archivo de usuario); con bypass la sesión arranca en Manual. Los otros modos (default,acceptEdits,plan,dontAsk) sí se aplican desde el proyecto en la terminal. Las sesiones en la nube tampoco hacen caso de bypass ni de dontAsk desde los archivos. - Cómo comprobarlo: si pusiste auto en el proyecto y la sesión arranca en Manual sin error, es esto. Mueve el ajuste a
~/.claude/settings.jsono usa--permission-mode auto. - Y el modo bypass:
bypassPermissions(igual que--dangerously-skip-permissions) se salta las preguntas, incluidas las escrituras en rutas protegidas como.gity.claude. La documentación lo limita a contenedores o máquinas virtuales donde no pueda hacer daño, y en Linux recomienda no ejecutarlo como root. Ni siquiera en ese modo se aprueban solas las reglas ask, los borrados de rutas críticas con rm niAskUserQuestion.
- Por qué: para que un repo no pueda decidir por ti cuánto se aprueba solo, Claude Code ignora
- Por qué: la forma más habitual de acabar en bypass es por costumbre o por copiar un alias. Puedes impedirlo tú mismo:
permissions.disableBypassPermissionsMode: "disable"funciona desde cualquier ámbito, no solo en los ajustes administrados, y un usuario puede ponerlo en su propio archivo para no poder entrar en bypass. Lo mismo conpermissions.disableAutoMode: "disable"si prefieres no delegar en el clasificador; con él,autodesaparece del ciclo deShift+Taby una sesión lanzada con--permission-mode autoarranca en Manual. - Cómo comprobarlo: añade la clave a
~/.claude/settings.json, valida el JSON conpython3 -m json.tool ~/.claude/settings.jsony arrancaclaude --dangerously-skip-permissions: según la documentación ya no debe entrar en bypass (nosotros no pudimos verlo sin una sesión iniciada). En una organización, ponlo en los ajustes administrados, donde nadie lo puede quitar.
- Por qué: la forma más habitual de acabar en bypass es por costumbre o por copiar un alias. Puedes impedirlo tú mismo:
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
- Por qué: la documentación oficial lo dice claro:
curlywgetno se aprueban automáticamente por defecto (en Manual preguntan como cualquier comando que no es de solo lectura), y puedes ponerlos enpermissions.deny. Pero una regla deny compara el comando tal como está escrito:deny: Bash(curl *)frenacurl https://…y no frena/usr/bin/curl https://…,sh -c 'curl …'ni un script de Python que abra una conexión. Y permitir soloWebFetch(domain:github.com)tampoco basta: si Bash está permitido, Claude puede usar cualquier otra herramienta de red. - La barrera real es el sandbox: con
/sandbox(osandbox.enabled: true), los comandos de Bash y sus procesos hijos corren aislados; en Linux, en otro espacio de red sin salida, y solo llegan a los dominios desandbox.network.allowedDomainsa través de un proxy. En Linux y WSL2 necesitabubblewrapysocat(sudo apt-get install bubblewrap socat); en Ubuntu 24.04 o posterior, AppArmor puede impedir que bubblewrap arranque, y/sandboxte dice cómo arreglarlo. - Cómo comprobarlo: abre
/sandbox; si solo ves la pestaña Dependencies, falta algo. Ojo: si el sandbox no puede arrancar, por defecto los comandos corren sin él; ponsandbox.failIfUnavailable: truesi quieres que Claude Code se niegue a arrancar.
- Por qué: la documentación oficial lo dice claro:
- Por qué: el sandbox envuelve los comandos de shell, no todo lo demás. Según la documentación del sandbox, quedan fuera: las herramientas Read, Edit, Write, WebFetch y WebSearch (siguen tus reglas de permisos: un
denyReaddel sandbox no frena Read, yallowedDomainsno limita WebFetch), los hooks, los servidores MCP locales, los monitores de plugins, la statusline yapiKeyHelper(corren con todos tus permisos), lo que escribes tú con!, los comandos deexcludedCommandsy los reintentos sin sandbox que Claude pida tras un fallo. - Además: por defecto el sandbox puede leer casi toda la máquina, incluidos
~/.sshy~/.aws/credentials, y hereda tus variables de entorno, secretos incluidos. - Cómo comprobarlo y cerrarlo: añade
sandbox.filesystem.denyReadpara tus credenciales ypermissions.denyconRead(~/.ssh/**)yRead(~/.aws/**)para las herramientas de archivos. Para que Claude no pueda pedir ejecutar fuera,sandbox.allowUnsandboxedCommands: false(el «Strict sandbox mode» de la pestaña Overrides). Para meter todo detrás de una sola barrera, ejecuta Claude Code dentro de un contenedor, una máquina virtual o un dev container.
- Por qué: el sandbox envuelve los comandos de shell, no todo lo demás. Según la documentación del sandbox, quedan fuera: las herramientas Read, Edit, Write, WebFetch y WebSearch (siguen tus reglas de permisos: un
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"network": {
"allowedDomains": ["github.com", "*.github.com", "registry.npmjs.org"]
},
"filesystem": {
"denyRead": ["~/.ssh", "~/.aws"]
}
}
}
- Por qué: en Manual, Claude Code pregunta antes de que sus herramientas de archivos lean o escriban fuera de la carpeta donde lo abriste, pero un comando de Bash que apruebes puede escribir en cualquier sitio al que llegue tu usuario. Desde la versión 2.1.314 existe
permissions.blockWritesOutsideWorkingDirectories: Write, Edit y NotebookEdit se niegan a escribir fuera de las carpetas de trabajo en todos los modos (lo contamos en esta novedad). También existepermissions.blockReadsOutsideWorkingDirectories(desde la 2.1.257) para las lecturas, que hace preguntar incluso en auto y bypass. - Cómo comprobarlo: añádelo a
~/.claude/settings.jsony pide a Claude que edite un archivo de otra carpeta: según la documentación debe negarse. Si necesitas que lea otro repo, añádelo con/add-diro--add-diren vez de abrir la mano. Recuerda que las reglas allow no aprueban escrituras en rutas protegidas (.git,.claude…): en Manual y acceptEdits siempre preguntan. - Para Bash: la barrera es otra vez el sandbox, que por defecto solo deja escribir en la carpeta de trabajo, un temporal y las carpetas que añadas.
- Por qué: en Manual, Claude Code pregunta antes de que sus herramientas de archivos lean o escriban fuera de la carpeta donde lo abriste, pero un comando de Bash que apruebes puede escribir en cualquier sitio al que llegue tu usuario. Desde la versión 2.1.314 existe
- Por qué: cada «Sí, y no volver a preguntar» se guarda como regla allow en
.claude/settings.local.json. Con el tiempo acumulas permisos amplios sin darte cuenta, y algunos equivalen a ejecutar cualquier cosa:Bash(python3 *),Bash(node *),Bash(bash *),Bash(npx *)oBash(git *)(este último incluyegit -c core.fsmonitor=…). - Cómo comprobarlo: una vez al mes abre
/permissions, revisa la pestaña de reglas y la de bloqueos recientes del modo auto, y borra lo que sobre. Cambia los comodines por comandos exactos (Bash(python3 -m pytest *)en lugar deBash(python3 *)). - Y recuerda quién manda: las reglas las aplica Claude Code, no el modelo. Lo que escribes en CLAUDE.md o en el prompt orienta lo que Claude intenta, pero no cambia lo que se permite. Si algo tiene que cumplirse siempre, va en una regla deny, en un hook PreToolUse (un hook que sale con código 2 bloquea incluso con un allow; y un allow del hook no anula un deny) o en ajustes administrados. Ojo con los mods que instales: sin ajustes administrados ni sesión de Team o Enterprise, un mod puede aprobar una llamada que una regla deny rechaza.
- Por qué: cada «Sí, y no volver a preguntar» se guarda como regla allow en
Tus candados personales, en un solo archivo que vale en todos tus proyectos (~/.claude/settings.json):
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"disableBypassPermissionsMode": "disable",
"blockWritesOutsideWorkingDirectories": true,
"deny": [
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.config/gh/**)"
]
}
}
Y la revisión de un repo ajeno antes de abrir Claude en él:
# ¿Qué configuración de Claude trae?
ls -la .claude/ .mcp.json CLAUDE.md AGENTS.md 2>/dev/null
# Hooks, env y helpers que se ejecutarían
python3 -m json.tool .claude/settings.json 2>/dev/null | grep -nE '"(hooks|env|apiKeyHelper|allow|additionalDirectories|enableAllProjectMcpServers)"'
# Skills con allowed-tools (no dependen de la confianza)
grep -rn 'allowed-tools' .claude/skills 2>/dev/null
# Servidores MCP que pediría conectar
claude mcp list # los de .mcp.json salen «⏸ Pending approval» hasta que los apruebes
El repositorio trae esta revisión como revisar-repo-ajeno.sh (solo lee archivos: en lugar de claude mcp list muestra el .mcp.json) y los dos JSON de ejemplo. Si empiezas un proyecto desde cero, la plantilla de proyecto ya trae estos permisos puestos.
Errores típicos
- Claude te sigue preguntando aunque pusiste el allow en el proyecto → la carpeta no tiene la confianza aceptada (o arrancaste en tu home) → abre
claudeen la raíz del repo una vez y acepta el diálogo. - Pusiste
defaultMode: "auto"en.claude/settings.jsony la sesión arranca en Manual → Claude Code ignora auto y bypass desde los ajustes del proyecto → muévelo a~/.claude/settings.jsono usa--permission-mode auto. - Bloqueaste
Bash(curl *)y crees que cortaste la red → la regla compara el texto y no frena/usr/bin/curlnish -c→ activa el sandbox conallowedDomainsyfailIfUnavailable. - Un
allow: Bash(aws s3 ls)no funciona → existe undeny: Bash(aws *)en algún ámbito, y deny gana siempre → quita o acota el deny. - El deny no hace nada → JSON inválido, ruta mal escrita o comando que no coincide literalmente →
claude doctor(busca «Invalid settings») y/permissions. - Lanzas
claude -pen un repo clonado para «solo echar un vistazo» → sus hooks y sus servidores MCP se ejecutan sin confianza → revisa.claude/antes y usa--setting-sources user,--bareodisableAllHooks.
Qué probamos y qué falta
En este PC (Linux, Claude Code 2.1.316), con una configuración aislada (CLAUDE_CONFIG_DIR) y sin iniciar sesión: en un repo de prueba con allow en el proyecto, claude -p y claude doctor muestran «Ignoring 2 permissions.allow entries… not been trusted», y el aviso desaparece al marcar hasTrustDialogAccepted; un hook SessionStart del proyecto se ejecutó con claude -p sin confianza y antes de «Not logged in», y con --setting-sources user, --bare y --settings '{"disableAllHooks": true}' no se ejecutó (lo repetimos el 1-nov con el mismo resultado); un .mcp.json autoaprobado por el repo aparece «⏸ Pending approval» en claude mcp list. No pudimos probar: el sandbox de red (este PC tiene bwrap pero no socat), que bypass y auto se ignoren desde el proyecto, ni disableBypassPermissionsMode y blockWritesOutsideWorkingDirectories en una sesión real (sin sesión iniciada la CLI se detiene antes en «Not logged in»). Esos puntos se apoyan en la documentación oficial del 1-nov-2026.
Preguntas frecuentes
¿Por qué Claude Code ignora el deny de mi settings.json?
Casi siempre es una de tres: el JSON no es válido (comentarios o comas al final; claude doctor muestra «Invalid settings»), la ruta no está escrita como crees (en el archivo de usuario, /ruta empieza en ~/.claude/; usa ~/ruta o //ruta/absoluta) o el comando no coincide literalmente (Bash(curl *) no frena /usr/bin/curl). Revisa con /permissions de qué archivo sale cada regla.
¿Un repo puede aprobarse sus propios servidores MCP?
En una sesión interactiva no: enableAllProjectMcpServers o enabledMcpjsonServers en el .claude/settings.json del repo se ignoran en una carpeta sin confianza, y claude mcp list los muestra como «⏸ Pending approval». Lo comprobamos en este PC. Pero con claude -p, en una carpeta nunca confiada, los servidores de .mcp.json se conectan sin preguntar, aprobados o no; usa --setting-sources user o --bare en repos ajenos.
¿El modo auto es seguro para trabajar en mi máquina?
Es mucho más seguro que bypassPermissions, porque un clasificador revisa los comandos y las peticiones de red y tus reglas ask y deny siguen valiendo. Pero decide un modelo, no tú, y la documentación recomienda sumar un sandbox o un contenedor como defensa adicional. Para código o repos que no conoces, empieza en plan o Manual.
¿--dangerously-skip-permissions en un contenedor está bien?
Es el uso para el que existe: la documentación lo indica para contenedores, máquinas virtuales o el sandbox runtime, y en Linux y macOS como usuario no root. Aun así, si el contenedor tiene tus credenciales o acceso a la red, un error o una inyección de instrucciones puede usarlas.
¿Qué diferencia hay entre deny y un hook PreToolUse?
Las dos las aplica Claude Code. El deny es declarativo y compara el patrón de la herramienta; el hook es un programa tuyo que puede mirar cualquier cosa (por ejemplo, la rama en la que estás) y bloquear con exit 2. El hook bloquea aunque haya un allow, y un allow que devuelva el hook no anula un deny ni un ask.