settings.local.json de Claude Code con secretos filtrados: rota las claves primero, luego deja de rastrearlo y añade .gitignore (2026)
Al elegir «Yes, and don't ask again», un comando con su contraseña puede quedar en .claude/settings.local.json. Apiiro halló 1.122 copias públicas con secretos. Solución: rota claves, luego deja de rastrearlo y añade .gitignore; reescribir el historial es un paso aparte de alto riesgo.

Resumen: si alguna vez subiste .claude/settings.local.json a un repositorio, no empieces borrando el archivo. El primer paso es rotar todos los secretos que ese archivo haya contenido. El segundo es dejar de rastrearlo y añadirlo al .gitignore del propio repositorio. La razón: cuando eliges «Yes, and don’t ask again», Claude Code guarda el comando aprobado tal cual como regla allow, y cualquier contraseña o token escrito en ese comando entra en el archivo. La empresa de seguridad Apiiro informó a principios de noviembre de 2026 de que encontró 104.185 copias de este archivo en GitHub público, y 1.122 contenían al menos un secreto. Este artículo se basa solo en la investigación de Apiiro y en la documentación oficial de Anthropic y GitHub. Todas las claves de los ejemplos son inventadas y la salida de los escaneos muestra solo rutas y tipos de coincidencia.
Qué es el archivo y cómo entran los secretos
.claude/settings.local.json es el archivo de ajustes «locales del proyecto» de Claude Code: solo tuyo, solo para ese proyecto. La documentación oficial de ajustes dice que cuando apruebas un comando Bash con «Yes, and don’t ask again», Claude Code guarda la aprobación como regla allow en este archivo, en la raíz del repositorio git.
Una regla puede ser un patrón (como npm test *) o un comando completo. La documentación oficial de permisos indica que una regla sin * solo coincide con un comando exacto. Si el comando que aprobaste llevaba una contraseña, ahora está en el archivo en texto plano. La forma es esta (los marcadores son inventados):
{"permissions":{"allow":["Bash(PGPASSWORD=<contraseña en texto plano> psql -h <host> -U <usuario> -c '...')"]}}
Por qué acaba en GitHub
La documentación dice que la primera vez que Claude Code escribe este archivo en un repositorio git, añade **/.claude/settings.local.json a tu archivo global de exclusiones de git, así que ningún repositorio de ese equipo lo sube. También dice que si creaste el archivo a mano, debes añadirlo tú mismo al .gitignore.
El problema es que esa protección vive en una sola configuración de git de un solo equipo. Según Apiiro, Claude Code nunca lo añade al .gitignore del propio proyecto, así que la protección no viaja con el proyecto: un clon en otra máquina, un contenedor, una carpeta que luego se convierte en repositorio o un archivo que ya estaba rastreado la pierden. Apiiro revisó 1.105 repositorios y en 539 un commit con Claude como coautor había modificado el archivo; deducen que Claude lo sube a menudo por su cuenta. Es una inferencia suya, no una declaración de Anthropic.
Qué encontró la investigación
Las cifras vienen de la investigación de Apiiro, publicada por The Hacker News. Al comprobarlo, la publicación de Apiiro quedaba tras la pantalla de verificación del sitio y no se abría. Todas las cifras de la lista, incluidas las 63 organizaciones y las 298 copias del settings.json compartido, aparecen en ese artículo de Hacker News. Ars Technica también cubrió la investigación (redondea algunos totales).
- 104.185 copias de
.claude/settings.local.jsonen GitHub público, en 103.617 repositorios. - 1.122 de ellas (cerca del 1,1 %) contienen al menos un secreto: 1.379 secretos distintos en total, de 63 organizaciones.
- Otros 734 secretos existen solo en versiones antiguas del archivo, normalmente tras borrarlo, en 509 repositorios. 211 forks llevan los mismos secretos que los originales.
- Apiiro no probó si los secretos siguen funcionando, así que es exposición, no una brecha confirmada. Una empresa notificada por los investigadores confirmó que su clave estaba activa.
- Dos escáneres habituales, gitleaks y TruffleHog, no marcaron 215 de los archivos, sobre todo contraseñas escritas directamente en comandos.
- También verás «2.539 secretos» en la prensa. Esa cifra suma el historial de git, el
settings.jsoncompartido y registros de chat, así que cuenta otra cosa que las 1.379 de arriba.
La solución, en este orden
1. Rota primero, lo demás después
La propia documentación de GitHub dice que, si el dato sensible es un secreto, el primer paso es revocarlo o rotarlo; una vez rotado ya no sirve para acceder y a veces con eso basta. Cambia todas las contraseñas, tokens y claves que ese archivo haya contenido, también las que solo están en commits antiguos. Prioridad: contraseñas que abren una base de datos directamente, claves de la nube, accesos SSH y tokens de GitHub / GitLab / npm. Para borrar y reemplazar claves de Anthropic, OpenAI y DeepSeek, mira API key filtrada: qué hacer.
2. Averigua dónde está rastreado y dónde estuvo
En cada repositorio, lista los archivos rastreados y todas las rutas que el historial tocó (imprimen rutas y resúmenes de commits, no el contenido):
git ls-files '*settings.local.json'
git log --all --name-only --pretty=format: -- '*settings.local.json' | sort -u
Luego usa este pequeño bucle, que imprime solo «ruta + tipo de coincidencia», para un escaneo rápido de las copias rastreadas. Es una demostración con reglas simples y no sustituye a un escáner de secretos de verdad:
for f in $(git ls-files '*settings.local.json'); do
grep -qE 'PGPASSWORD=|sshpass -p|mysql .* -p' "$f" && echo "$f hit: password-in-command"
grep -qiE '(token|secret|api[_-]?key|password)=' "$f" && echo "$f hit: key-or-token-assignment"
done
La salida se ve así (las rutas son inventadas):
.claude/settings.local.json hit: password-in-command
apps/api/.claude/settings.local.json hit: key-or-token-assignment
Ejecutamos estos comandos en un repositorio temporal con contraseñas falsas (git 2.47.3); la salida fue solo rutas, tipos de coincidencia y resúmenes de commits. Si eres un equipo, busca también en tu organización de GitHub .claude/settings.local.json y .claude/settings.json; los investigadores sugieren revisar ambos porque el settings.json compartido también tenía secretos (298 copias; investigación de Apiiro, publicada por The Hacker News).
3. Deja de rastrearlo y añádelo al .gitignore del repositorio
Añadirlo a .gitignore no basta: un archivo ya rastreado no se ignora. Primero haz que git deje de rastrearlo (--cached lo quita solo de git y conserva tu archivo local):
git rm --cached .claude/settings.local.json
echo ".claude/settings.local.json" >> .gitignore
git add .gitignore
git commit -m "Stop tracking Claude Code local settings"
Comprobamos los dos primeros pasos en el repositorio temporal: después, git ls-files ya no listaba el archivo y git check-ignore -v mostraba la regla de .gitignore. Ojo: esto no elimina las versiones antiguas del historial.
4. Limpia en tu equipo las reglas que contienen secretos
Abre el archivo en tu ordenador, aunque nunca se haya subido, y borra toda regla con una contraseña o un token. A partir de ahora aprueba patrones en lugar de comandos completos con contraseñas, y guarda los secretos en variables de entorno o en un gestor de secretos para que la regla guardada solo tenga el nombre de la variable. En la documentación oficial de permisos, Bash(npm run build) solo coincide con ese comando, mientras que una regla con * coincide con una familia de comandos; la segunda es la opción más segura en el aviso.
Un paso aparte y de alto riesgo: reescribir el historial de Git
Este paso es opcional y arriesgado, trátalo por separado. La documentación de GitHub es clara: una vez rotado el secreto ya no sirve para acceder, y seguir con la reescritura del historial «puede no estar justificado». Los efectos secundarios incluyen:
- Recontaminación fácil: un compañero con un clon anterior a la reescritura que simplemente descargue y suba puede devolver los datos antiguos; debe clonar de nuevo.
- Posible pérdida de trabajo ajeno: los commits en ramas antiguas chocan con el historial reescrito.
- Los forks, los clones locales y las vistas en caché de GitHub no se limpian, y las copias que otros ya se llevaron no se pueden recuperar.
Así que el orden es: rotar, confirmar en el panel del proveedor que los secretos antiguos están muertos y solo pensar en reescribir si hay un motivo claro (por ejemplo, el archivo también contiene datos que no puedes cambiar). Avisa antes a todos los colaboradores y ensaya en un espejo de respaldo. Este artículo no ofrece comandos copiables de reescritura ni de push forzado. Sigue solo la guía oficial de GitHub Removing sensitive data from a repository (recomienda git-filter-repo).
Cómo evitarlo en el futuro
- Pon
.claude/settings.local.jsonen la plantilla de.gitignorede tu equipo. Los investigadores también sugieren tratar carpetas de agentes como.claude/,.cursor/y.gemini/como sitios con secretos, igual que los.env. - Añade escaneo de secretos en pre-commit y CI, y asegúrate de que detecte contraseñas en texto plano dentro de comandos, no solo formatos de clave conocidos; gitleaks y TruffleHog no vieron esos 215 archivos.
- No pongas contraseñas en los comandos, usa variables de entorno y aprueba patrones.
- Por parte de Anthropic, Boris Cherny, de Claude Code, dijo en Hacker News que el equipo estudia cómo evitarlo y sugirió el modo automático y los escáneres de secretos; un usuario señaló que en modo automático los comandos sensibles aún pueden guardarse en los archivos de ajustes, y él lo calificó de buen hallazgo que el equipo sigue pensando. No hemos visto un anuncio oficial de cambio, así que guíate por la documentación oficial.
Preguntas frecuentes
¿Basta con borrar el archivo?
No. Las versiones antiguas siguen en el historial de git y los forks pueden tenerlas. Rota primero los secretos.
Mi repositorio es privado. ¿Importa?
La investigación solo contó repositorios públicos, así que no hay datos de los privados. Pero un secreto escrito en un archivo lo lee cualquiera que pueda leer el repositorio; si el archivo alguna vez tuvo uno, sigue el mismo orden.
¿Es lo mismo que settings.json?
No. settings.json guarda ajustes compartidos o personales; settings.local.json es la parte del proyecto que es solo tuya. Para rutas y prioridad, mira settings.json de Claude Code; para el aviso de permisos, Claude Code /permissions.
¿Otros errores de Claude Code que consultar?
Mira Errores de Claude Code.