DIRTY STATIC / DESPACHO Tutoriales08 NOV. 2026 • 15 MIN DE LECTURA
Un botón de permiso gigante amarillo de advertencia en una pared de concreto en una sala de servidores en blanco y negro, con un archivo de configuración abierto que derrama llaves de papel en el piso y franjas de peligro bajo los pies
TutorialesINTELIGENCIA PARA LA ERA DE LAS MÁQUINAS

Evita que Claude Code filtre secretos a GitHub

Una sola aprobación en Claude Code puede guardar una contraseña dentro de un archivo de proyecto que luego llega a GitHub. Este tutorial audita las reglas guardadas, rota cualquier cosa expuesta, deja de seguir el archivo local en el propio repositorio, reescribe reglas riesgosas para usar variables y agrega capas de escáner y protección de push que atrapan el siguiente error.

Empezar a leer ↓

Apruebas un comando útil en Claude Code y sigues. El comando revisó una base de datos o llamó a una API, así que llevaba una contraseña o un token en texto simple. Semanas después ese mismo proyecto va a GitHub, y la aprobación que olvidaste está en el repositorio para que cualquiera la lea.

Esa es la fuga que este tutorial detiene. Como informamos esta mañana en La fuga de Claude Code expone contraseñas en 1,122 repositorios, la empresa de seguridad Apiiro encontró 1,122 copias públicas de .claude/settings.local.json con al menos un secreto. El archivo no es malware y ningún atacante lo puso allí. Claude Code lo puso allí cuando alguien eligió la opción de no volver a ser preguntado.

Lo que vas a construir o aprender

Terminarás con un repositorio que es seguro para compartir y seguro para seguir usando con Claude Code. El archivo local de configuración se quedará en tu computadora y fuera de git. Ninguna regla de permiso guardada en ninguno de los archivos de configuración contendrá un valor secreto. Tus comandos se referirán a secretos por nombre de variable, un escaneo local revisará trabajo nuevo y GitHub bloqueará un push que lleve un patrón de secreto admitido.

También aprenderás cómo distinguir los dos archivos de configuración, que es la habilidad que evita una repetición. Un archivo es solo tuyo. El otro está construido para viajar.

ArchivoPara quién esDebería confirmarse
.claude/settings.local.jsonTú, en este único proyectoNo. Aquí es donde se guardan las aprobaciones permanentes de Bash
.claude/settings.jsonTodos en el proyectoSí, después de una revisión cuidadosa en busca de secretos y rutas privadas
~/.claude/settings.jsonTú, en cada proyecto en esta computadoraNo. Vive en tu carpeta personal, fuera del repositorio

La documentación de permisos de Claude Code dice que una aprobación de Bash guardada con la opción de no volver a preguntar va a .claude/settings.local.json en la raíz del repositorio git. La documentación de configuración dice que Claude Code agrega ese archivo a tu archivo global de exclusiones de git la primera vez que lo escribe en un repositorio. Esa protección vive en una computadora. Nunca va al archivo de ignorar del repositorio, así que no viaja a un clon nuevo, un compañero de equipo o un ejecutor.

Antes de empezar

Lee el orden antes de tocar un archivo. La rotación viene antes de la limpieza. Un secreto que estuvo en un repositorio público, o en el historial de git, debería tratarse como público incluso después de que el archivo se vea limpio. Eliminar la copia actual no elimina copias antiguas, bifurcaciones ni clones.

Respalda los dos archivos de configuración del proyecto fuera del repositorio antes de editarlos. Mantén ese respaldo fuera de git también. Nunca pegues un secreto real en un reporte de error, un chat, una captura de pantalla o un registro compartido mientras auditas. Los comandos abajo están construidos para mostrar nombres de archivo, números de línea y salida redactada donde la herramienta lo admite.

Luz de inspección sobre carpetas de configuración extendidas en una mesa de concreto, una carpeta marcada con una franja amarilla de advertencia Audita primero, rota segundo, limpia tercero. Ilustración generada por Dirty Static.

Paso 1: Audita las reglas guardadas en ambos archivos de configuración

Acción: abre .claude/settings.local.json y .claude/settings.json en un editor y lee cada regla de permiso a simple vista. Luego ejecuta /permissions dentro de Claude Code. La documentación dice que ese diálogo enumera todas las reglas de permiso y el archivo de configuración del que viene cada regla, lo que te ayuda a detectar una regla que no sabías que habías guardado.

Linux · macOS · Terminal

grep -n "Bash(" .claude/settings.local.json
grep -n "Bash(" .claude/settings.json

Resultado esperado: las búsquedas enumeran las reglas de Bash guardadas con números de línea. Una regla sin comodín cubre un comando exacto. Si ese comando exacto contiene una contraseña, un token, una ruta de clave privada con un valor o una dirección de base de datos con una contraseña dentro, marca ese valor como expuesto si el archivo se envió alguna vez. No copies el valor a ningún lugar nuevo. Escribe solo el nombre del servicio y el tipo de secreto, como contraseña de base de datos o token de API, para la lista de rotación en el Paso 3.

Paso 2: Revisa si el archivo local está seguido e ignorado

Acción: hazle a git dos preguntas separadas. Seguir e ignorar no son lo mismo, y una regla de ignorar no hace nada para un archivo que ya está seguido.

Linux · macOS · Terminal

git ls-files .claude/settings.local.json .claude/settings.json
git check-ignore -v .claude/settings.local.json
git status --short

Resultado esperado: git ls-files imprime el archivo local solo si git lo sigue. Esa salida es un problema, incluso si el segundo comando encuentra una regla de ignorar. git check-ignore -v imprime el archivo de ignorar y el patrón que coincidió cuando el archivo está ignorado en esta computadora. Ninguna salida significa que esta computadora ofrecería el archivo a una adición normal. Anota de qué archivo de ignorar vino la coincidencia. Una coincidencia de tu archivo global de exclusiones protege solo esta computadora.

Paso 3: Rota primero si algún secreto estuvo alguna vez en cualquiera de los archivos

Acción: trabaja la lista de rotación del Paso 1, más cualquier secreto que encuentres en el historial. Para cada valor, ve al servicio que lo emitió, revoca o cambia el valor antiguo, emite uno nuevo, guarda el nuevo en tu almacén de secretos, actualiza el lugar del que la aplicación lo lee y prueba la aplicación una vez.

Linux · macOS · Terminal

git log --all --oneline -- .claude/settings.local.json .claude/settings.json

Resultado esperado: el registro enumera cada commit que tocó cualquiera de los archivos de configuración. Si un commit listado llegó a un remoto público, trata cada secreto en esa versión como expuesto, incluso si el archivo actual está limpio. Apiiro contó cientos de secretos extra solo en versiones antiguas. Para un repositorio de equipo, también busca en la organización de GitHub el nombre del archivo local, porque un clon de un compañero puede haber enviado una copia que nunca viste. La rotación es lenta y molesta. También es el único paso que hace que un valor expuesto sea inútil para quien lo copió.

Paso 4: Deja de seguir el archivo local e ignóralo en el propio repositorio

Acción: elimina el archivo local solo del índice de git, para que la copia en disco se quede en su lugar. Luego agrega su patrón al archivo de ignorar del repositorio, para que la regla viaje con el proyecto. Usa la forma de patrón que la documentación de Claude Code usa para la entrada de exclusiones globales.

Linux · macOS · Terminal

git rm --cached .claude/settings.local.json
echo '**/.claude/settings.local.json' >> .gitignore
git add .gitignore
git status --short
ls -l .claude/settings.local.json

Resultado esperado: el estado muestra el archivo local como eliminado del índice y el archivo de ignorar como cambiado, mientras el último comando demuestra que el archivo local aún existe en disco para que Claude Code lo use. Confirma el cambio de ignorar y la eliminación del índice juntos, con un mensaje que diga lo que hiciste y por qué. Desde ahora un clon fresco tiene la regla de ignorar incluso en una computadora donde Claude Code nunca se ha ejecutado.

Paso 5: Reescribe reglas riesgosas como patrones y mueve secretos a variables

Acción: en el diálogo /permissions, elimina cada regla de permiso que contenga un valor secreto, en ambos archivos. Luego reconstruye las aprobaciones útiles en una forma segura. La documentación de permisos muestra la forma. Una regla con un comodín cubre una familia de comandos. Una regla sin comodín cubre un comando exacto, secreto incluido.

Forma de regla guardadaLo que llega al archivoVeredicto
Un comando exacto con un valor de tokenEl propio token, en texto simpleElimínalo y rota el token
Un patrón como Bash(npm run *)El patrón y ningún valorSeguro cuando la familia es estrecha
Un comando que nombra una variableEl nombre de la variable y ningún valorMejor forma para trabajo que necesita un secreto

Carga el valor en una variable de entorno mediante tu gestor de secretos o tu gestor de contraseñas, fuera de cualquier archivo que confirmes. Luego deja que Claude Code ejecute el comando en su forma de variable:

Linux · macOS · Terminal

curl -H "Authorization: Bearer $EXAMPLE_API_TOKEN" https://api.example.com/check

Resultado esperado: si apruebas ese comando con la opción de no volver a preguntar, el texto guardado en el archivo local nombra la variable. No contiene el valor. Mantén los patrones estrechos. Un patrón que permite cada llamada curl es una puerta más ancha de lo que la mayoría de los proyectos necesita.

Una protección más pertenece al archivo compartido, después de una revisión de equipo. La documentación de configuración usa una denegación de lectura para archivos de entorno como su ejemplo, y las reglas de denegación en un archivo de proyecto se aplican de inmediato. Agrega reglas como estas a .claude/settings.json para que la herramienta de lectura rechace archivos secretos por defecto:

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)"
    ]
  }
}

Resultado esperado: Claude Code se niega a leer esos archivos con su herramienta de lectura en este proyecto. Trata esto como una protección, no como toda la corrección. La corrección es que ningún valor secreto esté en un comando, una regla o un archivo seguido en primer lugar.

Una puerta de acero y un haz de escáner amarillo de advertencia que revisa un camión antes de que entre en una bóveda de concreto Los escaneos locales y la protección de push son la puerta. La rotación es lo que haces cuando la puerta estaba abierta. Ilustración generada por Dirty Static.

Paso 6: Escanea los archivos actuales y el historial completo con Gitleaks

Acción: instala Gitleaks desde su repositorio del proyecto. En macOS el repositorio enumera la ruta de Homebrew. Luego escanea la carpeta de configuración como archivos simples, y escanea el repositorio con su historial completo de git. El repositorio documenta tres modos de escaneo. El modo git lee el historial de commits. El modo dir lee archivos en disco.

Linux · macOS · Terminal

brew install gitleaks
gitleaks dir --redact -v .claude/
gitleaks git --redact -v .

Resultado esperado: cada escaneo imprime hallazgos con un archivo, una línea y un nombre de regla, con valores redactados de la salida. Vuelve al Paso 3 para cualquier hallazgo real en el historial. Un escaneo limpio no es prueba por sí solo. Apiiro ejecutó Gitleaks y TruffleHog sobre los archivos con fuga y encontró 215 archivos que ninguna herramienta marcó, la mayoría de las veces porque una contraseña simple dentro de un comando normal no se parece a un formato de clave conocido. Tu auditoría a simple vista en el Paso 1 sigue siendo parte del sistema.

Paso 7: Agrega un hook de commit para que el siguiente secreto se detenga temprano

Acción: agrega Gitleaks mediante el marco de hooks de commit que su repositorio documenta. Instala el marco primero siguiendo la guía de instalación en pre-commit.com, y luego crea .pre-commit-config.yaml en la raíz del repositorio con el bloque del repositorio de Gitleaks:

repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.2
    hooks:
      - id: gitleaks
Linux · macOS · Terminal

pre-commit autoupdate
pre-commit install
pre-commit run --all-files

Resultado esperado: el hook se instala en este clon y una ejecución completa informa el árbol actual. Confirma el archivo de configuración para que cada compañero obtenga la misma configuración, y pon el comando de instalación en las notas de configuración del repositorio, porque cada clon aún necesita que el paso de instalación se ejecute una vez. Un hook local puede ser omitido por la persona que hace el commit, así que es una protección para errores honestos. El paso siguiente es el respaldo del lado del servidor.

Paso 8: Activa la protección de push de GitHub

Acción: abre el repositorio en GitHub y ve a Settings, y luego a Advanced Security. La documentación de GitHub dice que debes activar Secret Protection primero si aún no está activado. Bajo Secret Protection, a la derecha de Push Protection, elige Enable. La documentación enumera propietarios de repositorio, propietarios de organización, gestores de seguridad y usuarios con el rol de administrador como las personas que pueden hacer esto.

Resultado esperado: GitHub ahora bloquea un push que lleva un patrón de secreto admitido y levanta una alerta cuando un colaborador omite el bloqueo. La documentación de GitHub también describe una forma de protección de push para cuentas personales que protege tus envíos a cualquier repositorio público. Activa eso también si tu cuenta lo ofrece, porque la fuga en esta historia empieza en una computadora portátil, no en un servidor. La protección de push cubre patrones conocidos. No reemplaza el hábito de variables del Paso 5 para contraseñas simples.

Verificación

Trabaja esta lista en orden. Cada línea debería cumplirse antes de que llames limpio al repositorio.

Linux · macOS · Terminal

git ls-files .claude/settings.local.json
git check-ignore -v .claude/settings.local.json
git add .claude/settings.local.json
gitleaks git --redact .

El primer comando no imprime nada, así que el archivo local no está seguido. El segundo imprime tu archivo de ignorar del repositorio como la fuente de la coincidencia, no solo tu archivo global de exclusiones. Un intento normal de adición informa el archivo como ignorado. Dentro de Claude Code, /permissions no muestra ninguna regla que contenga un valor secreto, y una aprobación fresca para un comando seguro en forma de variable guarda una regla que nombra solo la variable. El escaneo del historial puede aún enumerar hallazgos antiguos para valores rotados. Eso es esperado hasta que tu equipo tome una decisión separada sobre el historial. La rotación es lo que te protege mientras tanto.

Solución de problemas

ProblemaCausa probableSolución
El archivo local aún se muestra como seguido después de agregar la regla de ignorarLas reglas de ignorar no dejan de seguir un archivo que git ya sigueEjecuta el Paso 4 en su totalidad. La eliminación del índice es el paso para dejar de seguir, y la regla de ignorar lo mantiene fuera después
git check-ignore no imprime nadaNinguna regla de ignorar coincide en esta computadora, o el archivo ya está seguidoAgrega el patrón al archivo de ignorar del repositorio, confírmalo y repite el Paso 2 después del Paso 4
Un escáner no informa hallazgos pero viste una contraseña en una reglaEl valor es una contraseña simple dentro de un comando normal, que los escáneres a menudo pierdenConfía en la auditoría a simple vista. Rota el valor, elimina la regla y reconstrúyela en forma de variable
La regla riesgosa regresa después de una semanaUna aprobación nueva guardó el comando exacto de nuevoRevisa qué comando se aprobó, mueve su secreto a una variable y aprueba la forma de variable en cambio
El secreto está en el archivo compartido de configuraciónUna regla o un valor se guardó o se pegó en el archivo de equipo, que está construido para confirmarseRota el valor, elimínalo del archivo compartido y revisa el archivo antes de cada commit que lo toque
El archivo actual está limpio pero el historial aún contiene el secretoUn commit antiguo llevó el archivo antes de que lo limpiarasMantén el valor rotado como la protección. Decide sobre reescribir el historial como equipo, con aviso a todos los que clonan el repositorio
La protección de push bloquea un push que crees seguroEl texto enviado coincide con un patrón de secreto admitidoLee el mensaje de bloqueo, elimina o reemplaza el texto coincidente y usa la ruta de alerta de omisión solo para una falsa alarma demostrada que tu dueño de seguridad acepte

Próximos pasos

Ejecuta esta misma auditoría en cada repositorio donde uses Claude Code, empezando con los públicos. Luego escanea las otras carpetas de configuración de agente que uses con el mismo ojo, porque cualquier herramienta que guarde aprobaciones o transcripciones en una carpeta de proyecto puede llevar el mismo riesgo. Agrega el escaneo del historial a tus revisiones de construcción en un horario, para que las reglas nuevas y los commits nuevos se revisen sin que nadie recuerde ejecutar un comando a mano.

El hábito a conservar es pequeño. Aprueba patrones, no comandos exactos con valores. Refiérete a secretos por nombre de variable. Deja que el archivo local se quede local, en el archivo de ignorar del repositorio y no solo en tu global. Un clic de aprobación aún te ahorrará tiempo. Solo no publicará tus contraseñas mientras lo hace.

Datos verificados el 8 de noviembre de 2026, contra la documentación de permisos y configuración de Claude Code, el repositorio del proyecto Gitleaks y la documentación de protección de push de GitHub. Este tutorial sigue los comandos documentados y los hallazgos en la investigación de Apiiro enlazada abajo. No afirma que la secuencia completa se haya ejecutado en una cuenta en vivo con secretos reales.

Fuentes

■

FIN DE LA TRANSMISIÓN

Mantén la curiosidad. Cuestiónalo todo.

SIGUE EL DESCENSO

MÁS DE DIRTY STATIC ↘