← Artículos

Abrí el archivo de permisos de Claude Code: 297 reglas

· 8 min de lectura

Cada vez que apruebas un comando en Claude Code con "Yes, and don't ask again", el comando entero queda guardado como regla allow en settings.local.json. Conté las mías el 26 de agosto de 2026: 297 reglas en el archivo de usuario, 284 reglas Bash sumando el del proyecto, 40 con comodín y 3 con una clave de Google escrita en texto plano.

Nunca había abierto ese archivo. Llevo meses usando Claude Code todos los días y la tercera opción del diálogo de permisos —"Yes, and don't ask again"— la elijo sin pensar, varias veces al día. Es cómoda. Ese es el problema entero. Ayer lo conté. No lo abrí: corrí un script que cuenta y señala, pero que nunca imprime el valor de nada. Esta es la autopsia.

Qué guarda exactamente ese archivo

La documentación oficial de Claude Code lo dice sin rodeos: "When Claude asks permission to run a Bash command and you choose 'Yes, and don't ask again', Claude Code saves that approval as an allow rule in .claude/settings.local.json". Lo importante está en una palabra que no aparece por ningún lado: resumen. No guarda un resumen. No guarda el nombre del programa. Guarda el comando entero, literal, envuelto en Bash(...). Si esa vez pegaste una variable de entorno con una credencial delante del comando, la credencial entró al archivo con todo lo demás. Y hay un detalle que explica la velocidad a la que crece. La documentación de permisos dice que cuando apruebas un comando compuesto, Claude Code guarda una regla separada por cada subcomando que necesitaba aprobación, hasta cinco reglas de un solo "sí". Un clic, cinco entradas nuevas.

Este sistema es el que enseño dentro de la comunidad MÁQUINA IA: las estaciones, los gates y el código que lo sostiene.

La medición: 297 reglas que no recuerdo haber aprobado

Estos son mis números del 26 de agosto de 2026, medidos con Claude Code 2.1.246:

  • 297 reglas allow en mi archivo de usuario, el que vive en la carpeta .claude de mi carpeta personal.
  • 284 reglas de tipo Bash sumando ese archivo y el del proyecto en el que estaba parado.
  • 40 de esas 284 llevan un comodín.
  • 3 guardan una clave de Google en texto plano.

Tres de 284 suena a nada hasta que lo dices completo: es una clave de Google entera, tres veces, escrita en un archivo de texto que se copia cuando se copia la carpeta del proyecto. Y no recuerdo ni una sola de esas 284 decisiones. Cada una me costó un clic y medio segundo. Ninguna me pareció importante en su momento, porque ninguna lo era por separado.

El dato que no esperaba: 644 contra 600

Esto es lo que me hizo escribir el artículo en vez de limpiar y callarme. En la misma carpeta .claude conviven dos archivos. El historial, history.jsonl, tiene permisos 600: en la terminal se lee como -rw-------, o sea que solo mi usuario puede abrirlo. El de permisos, settings.local.json, tiene 644: -rw-r--r--, legible por cualquier otro usuario y por cualquier proceso de la máquina. El archivo que puede llevar una credencial dentro se guarda más abierto que el que guarda mis conversaciones. Hay que decirlo con precisión, porque es fácil convertir esto en un titular falso: 644 es el modo normal de un archivo de configuración en cualquier sistema Unix, y el raro de los dos es el historial, que se sale de la norma por ser más estricto. Nadie hizo nada mal. Pero si te sentaran delante de los dos archivos y te dijeran "blinda uno", no elegirías el historial.

Lo que Claude Code sí cubre, y por qué no me salvó

La parte honesta antes de acusar a nadie. La misma documentación oficial dice: "The first time Claude Code writes the file in a git repository that doesn't already ignore it, it adds **/.claude/settings.local.json to your global git excludes file, so the file stays out of your commits in every repository". Lo comprobé a mano en mi máquina: la primera línea de mi archivo de excludes global es exactamente ese patrón. Mi archivo de permisos no viajó en ningún commit, ni en este repositorio ni en ningún otro. La protección existe y funciona. Pero la protección es contra el repositorio, no contra el disco. Y el riesgo real no tiene nada de sofisticado: un respaldo de Time Machine viejo, una copia de la carpeta que le pasas a alguien por WeTransfer, un zip del proyecto, una carpeta sincronizada a la nube, una pantalla compartida con el editor abierto. El denominador común de casi todos esos escenarios no es un ataque. Es una copia.

Los 40 comodines: la parte que resultó no ser el problema

Cuarenta de mis 284 reglas llevan un asterisco. Suena peor de lo que es, y aquí es donde contar sirve de verdad: para saber cuál de los dos miedos era el real. La versión 2.1.246 de Claude Code, publicada el 25 de agosto de 2026 a las 19:17 UTC según el registro de npm, añadió un aviso al arrancar para una clase concreta de comodín: el que va antes del subcomando. La documentación de permisos explica por qué importa. En una regla como Bash(git * main), el asterisco "stands in for the subcommand, so Claude Code matches every git subcommand and every option before it. That includes -c, which makes git run a program you name". Traducido: una regla que creíste que aprobaba un merge también aprueba que git ejecute cualquier programa que el comando nombre. Revisé mis 40 una por una. Ninguna es de esa clase. Treinta y cinco terminan en asterisco, del estilo Bash(python3 *), y cinco lo llevan dentro de un patrón de nombres de archivo. La documentación de errores de Claude Code confirma que ese no es el caso que dispara el aviso: dice explícitamente que no advierte sobre "rules in which no word other than an option follows the *, such as Bash(git *)". Así que mi problema no eran los comodines. Eran tres reglas con una clave dentro. Sin contar, habría limpiado lo que no tocaba y habría dejado lo que sí.

Cómo entra una clave en un archivo de permisos

La reconstrucción es aburrida, y por eso le pasa a todo el mundo. Un día necesitas correr un script que habla con una API. Tienes la clave a mano, en el portapapeles. La pegas delante del comando porque es más rápido que abrir un archivo de entorno: MI_CLAVE=AIzaSyEJEMPLO_NO_REAL_123 python3 subir.py Funciona. Claude Code te pregunta si puede ejecutarlo. Dices que sí y que no vuelva a preguntar, porque lo vas a correr diez veces más esa tarde. Y esa línea entera, con la clave dentro, se convierte en una regla permanente. No hay ningún momento en el que el sistema te engañe. Hay un momento en el que tú vas con prisa. La clave de arriba es inventada, por cierto: ninguna credencial real se escribe en un artículo, ni siquiera para ilustrar.

Qué hice, y en qué orden

El orden importa más que los comandos, porque el error típico es limpiar primero y quedarse tranquilo con una credencial que sigue viva.

  1. Contar sin abrir. Un script que devuelve tres números y los índices de las reglas sospechosas, sin imprimir jamás el valor. Si el tercer número viene vacío, no hay nada que hacer y se repite el chequeo dentro de un mes.
  2. Rotar antes que borrar. Borrar la regla no desactiva nada. Si la clave empieza por AIza es de Google: se crea la nueva en la consola, se borra ahí la expuesta, y ese es el único paso que de verdad la deja inservible.
  3. Limpiar después. Con respaldo, y con Claude Code cerrado: si el programa reescribe el archivo encima mientras editas, pierdes el cambio.
  4. Borrar el respaldo. El archivo .bak guarda la clave vieja tal cual. Un respaldo que nadie borra es el mismo problema con otro nombre.
  5. Cambiar el hábito. La clave vive en un archivo de entorno fuera del proyecto, con permisos 600, y se carga justo antes de correr el comando. La regla que Claude Code guarda entonces es Bash(python3 subir.py), sin nada dentro.

El paso 5 es el único que cierra el ciclo. Los cuatro primeros son limpieza; ese es el que impide que vuelva a llenarse.

El dato honesto

Los números 297, 284, 40 y 3 salen de una sola máquina: la mía. No son una estadística del ecosistema, son una medición. Tu archivo puede tener cuatro reglas o mil, y la única forma de saberlo es contar el tuyo. El detector busca formas conocidas: cadenas tipo AIza, tipo sk-, y variables cuyo nombre lleva KEY, TOKEN, SECRET o PASS. Una contraseña que parezca una palabra normal se le escapa entera. Una lista vacía no es un certificado de limpieza, es la ausencia de una coincidencia. Y lo más importante, porque es lo que más se tergiversa: esto no es un fallo de Claude Code ni una filtración. Es comportamiento documentado. La regla necesita el comando entero para saber qué fue exactamente lo que autorizaste; guardar menos sería peor. El aviso nuevo de la 2.1.246 cubre la clase del comodín, y no dice nada de la clase que guarda claves, porque no puede: esa la escribí yo, una tarde, con prisa. El permiso se da una vez. El texto se queda.

Preguntas frecuentes

¿Claude Code filtra mis credenciales?
No. Es comportamiento documentado, no una filtración. Cuando apruebas un comando con "Yes, and don't ask again", Claude Code guarda ese comando entero como regla allow porque necesita saber qué autorizaste exactamente; guardar solo un resumen sería menos seguro. Si tú pegaste una credencial delante del comando, la credencial forma parte del comando y queda escrita con él. El archivo se queda en tu máquina y Claude Code lo mantiene fuera de git.
¿El archivo settings.local.json se sube a GitHub?
No, si lo creó Claude Code. Su documentación oficial dice que la primera vez que lo escribe en un repositorio que no lo ignora, añade el patrón **/.claude/settings.local.json a tu archivo de excludes global de git, así que queda fuera de tus commits en todos los repositorios. Lo verifiqué en mi máquina. Si creaste el archivo tú a mano y Claude Code todavía no lo ha escrito, tienes que añadirlo al .gitignore por tu cuenta.
¿Borrar la regla desactiva la clave que quedó escrita?
No. Borrar la regla solo quita el texto del archivo de permisos; la credencial sigue siendo válida en el servicio que la emitió. El único paso que la desactiva es rotarla en la consola donde nació: crear una nueva primero para no cortar lo que tengas corriendo, borrar allí la expuesta y solo después limpiar las reglas. Y acuérdate de borrar el respaldo .bak, que guarda la clave vieja tal cual.
¿Son peligrosas las reglas con comodín?
Depende de dónde esté el asterisco. La clase que preocupa es el comodín antes del subcomando, como Bash(git * main): la documentación de permisos explica que ahí el asterisco también cubre las opciones metidas antes, incluida -c, con la que git puede terminar ejecutando un programa que el comando nombre. Claude Code avisa al arrancar sobre esas desde la versión 2.1.246. Un comodín al final, como Bash(git *), es amplio pero no dispara el aviso.
¿Cada cuánto conviene revisar el archivo?
Una vez al mes basta si trabajas solo, y siempre antes de compartir la carpeta del proyecto, de grabar pantalla o de pasarle el repositorio a otra persona. El archivo es por carpeta, no hay uno solo: si tienes varios proyectos, cada uno tiene el suyo y el chequeo hay que repetirlo en cada uno. Heredar un repositorio ajeno también merece una pasada, porque esas reglas no las aprobaste tú.

Fuentes