---
layout: post.njk
source: https://yage.ai/share/claude-code-dont-ask-again-secret-leak-20261111.html
web_feed:
  articleId: cmwfmbsqs0008n9ye4u6pf52u
  feedSourceId: webfeed_yage_ai
  guid: https://yage.ai/share/claude-code-dont-ask-again-secret-leak-20261111.html
  sourceUrl: https://yage.ai/share/claude-code-dont-ask-again-secret-leak-20261111.html
speaker: yage.ai
title: |-
  点下「不再询问」之后：为什么近半数泄密配置是由 Claude
  Code 自己提交到 GitHub 的
date: '2026-11-12'
summary: 文章讨论了在使用 Claude Code 时，用户点击“不再询问”后，将包含明文密码和IP的终端命令写入本地配置文件（.claude/settings.local.json）的风险。研究发现，近一半的泄密配置是由 Claude 亲手提交到 GitHub 的。原因在于工具在处理本地配置时，对 Git 忽略规则的修改存在双重标准，且在用户让 AI 提交代码时，模型会漏掉机密文件。文章指出，传统的扫描工具难以检测到隐藏在命令行参数中的明文密码。为解决此问题，建议用户将密码与命令分开，使用环境变量或命令行工具注入内存，而不是直接在命令字面量中输入明文密码。
area: tech-engineering
category: ai-application
tags:
  - ai-tooling
  - ai-workflow
  - github-security
  - code-security
  - configuration-management
people:
  - Boris Cherny
companies_orgs:
  - Anthropic
products_models:
  - Claude Code
  - Claude
media_books: []
draft: true
status: evergreen
---

平时用 Claude Code
进行连接数据库、登录服务器或者调用外部接口等操作，我们经常在终端中看到一个确认对话框。为了避免每次都要按回车键，很多人会默认选择第
2 个选项，即允许并以后不再询问。项目文件夹里面有一个
.claude/settings.local.json
配置文件，专门用来记录本机放行的规则。点击这个按钮之后，工具一方面会记住你允许使用这个数据库连接工具，另一方面也会把你输入的整行带明文密码和公网
IP 的命令原封不动拷贝到这个文件里。

安全组织 Apiiro
最近发布了一份扫描报告，在 GitHub 上的 1,994
个公开代码仓库里，发现了 2,539
个由这种配置暴露出来的有效密钥。很多程序员以为他们从来没手动把配置文件夹传到代码库中过。但
Apiiro 在追查提交历史之后发现，近一半的泄露文件是主人叫 Claude
帮忙提交代码，Claude 亲手打包传上 GitHub 的。

## 为什么一句临时命令会变成连扫描器都漏掉的密码本？

这一切都源于一次次的图省事顺手放行。你让 AI
帮忙查一下线上测试库的数据，或者登录远端机器看一眼日志，AI
经常会拼出一行单次运行的完整终端命令。为了省掉交互弹窗，它会把密码直接塞进命令行里，拼成
PGPASSWORD=明文密码 psql -h 公网地址 或者
sshpass -p 明文密码 ssh root@公网地址
这样的格式。你一旦点下允许且不再询问，这整句话就会原样写进
.claude/settings.local.json
的白名单数组里。一个原本用来记权限开关的文件，就这样变成了同时存着大门钥匙和门牌号的明文密码本。

这本密码本已经在公开代码库里铺开了。前面提到的 1,994 个仓库、2,539
个密钥，覆盖了历史提交记录和共享配置等多个地方；即便只看现在还挂在
GitHub 默认分支上的 104,185 个 .claude/settings.local.json
文件，其中也有 1,122 个文件直接存着明文凭证。

这批现存文件里一共直接存着 1,379
个有效凭证。它们在默认分支上躺了中位数 217
天，一直处于公开可查的状态。

其中光是有公网地址的数据库密码就有 379 个，公网服务器的登录口令有 43
个。此外还有 122 个可绕过所有数据行安全策略的 Supabase
服务端高权限密钥，以及 103 个能控制账户下所有项目的 Supabase
账户令牌，其余则是各类云平台与第三方接口钥匙。

为什么这么多团队都装了防泄密扫描器，却仍然无法阻止这些文件的泄露呢？研究人员使用开源社区最常用的两种检测工具
gitleaks 和
TruffleHog，对这批已知的含有敏感信息的文件进行了扫描。令人惊讶的是，这两款工具竟然同时遗漏了
215 个文件，漏检率达到了
19.2%。究其原因，传统的扫描工具通常依赖于识别带有 sk- 或
ghp_
等前缀的乱码密钥。然而，一旦这些数据库明文密码隐藏在普通的命令行参数中，它们对扫描工具来说并不比普通的英文单词更为显眼。

点击不再询问后，带明文密码与公网地址的命令原样写入项目配置文件并随提交外泄

## 既然官方说「创建时就自动隐藏了」，为什么近一半是
Claude 自己传上去的？

这份报告在 11 月 7 日发上 Hacker News
以后，引发了大量开发者的追问。Claude Code 的团队负责人 Boris Cherny
当天就出来解释，这个本地配置文件本意就是为了留在单机上才设计的。他声称
Claude Code 创建这个文件时会自动把文件加到 gitignore
里，所以泄露的文件都是用户手动创建并且签入仓库的。

但翻开 Claude Code v2.1.299
客户端的安装包代码，就会发现真实逻辑跟他的说法对不上。早期版本的确会将忽略规则写入随代码库移动的
.gitignore 文件中。但有用户抱怨工具修改了项目文件后，官方在
2025 年底改变了这一策略，多张社区报错工单都提及了这一更改导致的泄密。目前，客户端在创建
.claude/settings.local.json 时不会修改项目自身的
.gitignore，而是在只存在于当前这台电脑上的全局 Git 忽略清单
~/.config/git/ignore 中写入一个条目。

这种只针对当前电脑的机制，在两个常见场景下会直接失效。第一种情况，如果你在一个新建的空文件夹里先用
Claude 并点了不再询问，之后才运行 git init
初始化代码库，客户端当时没检测到代码库，就会直接跳过不写忽略规则。第二种情况，就算客户端往当前电脑写上了全局忽略规则，那条规则也只留在这台电脑上；一旦你把项目拷到另一台电脑或放进容器里，保护就自动消失了。

类似地，遇到打包发布软件包的场景，打包的工具也不会去查看 Git
的全局忽略清单。Lakera
安全公司在今年 4 月发布的软件包扫描报告也发现，在公开发布的 428 个
npm 安装包中，它们直接把本地的这个配置文件放了进去，其中有 30
个包放了有效的密钥。

而更致命的是 Claude Code 的提交行为。安装包的代码显示，即使
.claude/settings.local.json 进入了 Git
的追踪列表，客户端在检测后会默默地记录一个内部统计日志，而不会向用户给出任何警告，并且会继续往里面追加新的密码。

到了用户真正让 Claude 帮忙提交代码这一步，防线彻底失守。在官方给
Claude 自己的 Git 提交系统提示词中，特别提醒模型不要提交
.env 或 credentials.json
等机密文件，却偏偏漏掉了自家的
.claude/settings.local.json。因此在 1,105
个可查清历史记录的泄密仓库中，有 539 个是用户让 Claude
帮忙提交代码时，由带着 Co-Authored-By: Claude
署名的提交亲手传上 GitHub 的，占比达 48.8%。

## 安装包里早就有密码过滤器，为什么只保官方云端、不保你的本地硬盘？

看到这里你可能会想，把命令放到文件之前检查有没有密码，难道是一件很难的事吗？在这次
Hacker News 的讨论里，Boris Cherny 给出的解释是，Claude Code
历史上从来没有做过这个机密清理，因为市场上已经有不少现成的工具，他们正在探索防止泄密的原型方案。

但事实上，社区早在一年多前就已经发现了这个坑。2025 年 8 月 11
日，一位开发者向 Claude Code 的官方仓库提交了一份附带复现步骤的安全漏洞报告，指出获批的命令会原样把明文密码保存在
settings.local.json 里。官方的工程师没有任何回复，搁置近 5
个月后，官方机器人在次年年初直接给这张工单标上不计划修复并自动关掉。

更令人惊讶的是，翻开客户端安装包的云端同步模块，里面明明躺着一段现成的密码过滤代码。这段代码会逐条扫描用户的
permissions.allow
放行规则，一旦发现某条规则看起来包含凭证，就会当场把它剔除，连给用户的提示语都已经写好了。

既然这个现成的过滤代码已经在安装包里了，为什么我们还是可以在本地配置文件里看到明文密码呢？原因在于这段官方提供的过滤代码，只在用户开启官方云端远程会话功能、把本地配置传到
Anthropic
的云服务器上时才启用。但用户点击不再询问并把命令写到本地项目文件夹里，程序就不会调用这个现成的过滤器。只保官方云服务器，不保用户本地代码库，这种双重标准就藏在同一个安装包里。

对此，Boris 在回应中还建议社区成员不要再用放行规则，而改用让后台 AI
分类器来判断命令是否危险的自动模式。但评论区有读者当场指出，自动模式的后台分类器一旦遇到带密码、连外部服务器的敏感命令，按设计就会不敢作主，退回人工弹窗让你点确认。你一点永久允许，密码照样写进同一个文件里。面对这个死循环，Boris
当场只能承认这位读者抓得准，说团队还得再想办法。况且自动模式本身的拦截能力也远没有宣传的那么可靠，香港科技大学在 10
月底刚更新的独立评测测试了 128
个日常开发任务，发现遇到操作范围交代不清的指令，自动模式有 81.0%
的危险动作根本没拦住。

同一个安装包里的双重标准：上传官方云端时自动过滤权限规则中的密码，写入本地代码库时却直接放行

## 现在花 30
秒怎么自查，以后怎么喂密码才不会留痕？

既然我们既不能指望工具自带的单机隐藏功能，也不能指望自动模式，那我们就自己动手把漏洞堵上。现在只需花
30 秒做两件事，就能让你的代码库彻底免疫。

第一步，不信单机全局隐藏，把 .claude/ 写到每个项目自己的
.gitignore 文件里；如果项目要发布软件包，还要写到
.npmignore。你可以在电脑上搜一下现有的
.claude/settings.local.json，看看里面有没有以前顺手放行的明文密码。

第二步是把批准运行什么命令和密码具体是什么彻底分开。平时让 Claude
Code
连数据库或登服务器，不要用明文密码直接写在命令的字面量里，而是用环境变量名，或者用
1Password 的命令行工具 op run --env-file .env -- claude
在启动时把密码注入内存。

这样即使你偷懒点了 100 次允许且不再询问，Claude Code 只会把
PGPASSWORD=$DB_PASSWORD psql -h 主机地址 这样的变量名写到
.claude/settings.local.json。就算这个文件真的传到 GitHub
上，别人拿到的也只是个空壳。