AREXOpen in interactive Feed

AREX Feed Article

GitGuardian 独立复核 Claude Code 密钥泄露:公开 GitHub 23,276 个仓库含 31,088 个密钥、17% 检测时仍有效,Docker Hub 镜像另涉 613 个

November 9, 2026

公开 GitHub 上,23,276 个仓库的 .claude/settings.local.json 共含 31,088 个不同密钥,其中 5,343 个(17%)在检测时仍然有效。这是安全厂商 GitGuardian 于 11 月 9 日在发布的独立复核结果,统计范围覆盖 2025 年 1 月至 2026 年 11 月 7 日被推送到公开 GitHub 的内容。GitGuardian 还实测了 GitHub 之外的出口:公开 Docker Hub 镜像中的 Claude Code 设置文件携带 613 个不同密钥、99 个有效。月度泄露量在 2026 年 4 月达到 12,535 次的峰值后,到 10 月降至 959 次,降幅 92%——至于为什么下降,GitGuardian 自己也说还不知道。

这组数字比 Apiiro 几天前公布的原始结果大出 20 多倍。11 月 5 日, 报告了同一问题的机制:用户对 Claude Code 提议的一条命令选择「Yes, and don't ask again」后,整条命令——包括其中的 API key——会原样作为 allow 规则写进项目目录下的 .claude/settings.local.json。Apiiro 的扫描在公开 GitHub 上 103,617 个仓库中找到 1,122 个含真实密钥的文件、1,379 个不同密钥,涉及 63 家组织,但没有测试这些凭据是否还能用(据 报道)。Claude Code 会在本机把该文件排除在 git 之外,但仓库本身没有任何防护——旧克隆、其他机器或已被跟踪的文件,照样会把它提交上去。

连续监控比一次性快照多看到什么

GitGuardian 的研究者在博文里交代了选题来源:2026 年初他在研究 n8n 时,不断在 Claude Code 设置文件里发现 n8n 的 API key,于是把这项分析排进了自家 State of Secrets Sprawl 2027 报告的计划;Apiiro 11 月 5 日先发布了同主题分析,他把准备好的数据刷新到本周提前公开。

数字差异来自方法。Apiiro 的代码搜索看到的是 11 月 1 日至 3 日默认分支上的文件,外加一次覆盖 43,120 个仓库和 211 个 fork 的历史回溯,数出当前副本中的 1,379 个密钥,外加历史版本中的 734 个。GitGuardian 扫描的是每次公开提交被推送时的内容,包括后来被删除、改写或 force-push 掉的版本,数出 31,088 个。博文的说法是:「两个数字都对。第二个数字,才是那些本该被轮换的凭据。」——Apiiro 问的是今天还暴露着什么,用保守的过滤条件、不测有效性;GitGuardian 问的是曾经被推送过什么,并统计其中自动检测判定有效的凭据。

有效性是 Apiiro 当时留白、这次复核补上的一环。GitGuardian 对每条公开检测都运行自动只读检查,博文声明这次没有为任何凭据做重放。在检查返回判定的地方,.claude/settings.local.json 中 67% 的出现次数有效,.claude/settings.json 中为 57%。按不同密钥计,31,088 个中 5,343 个(17%)在检测时有效。没有配套验证器的检测器一律不计入「有效」,所以这是一组下限。作为参照,Apiiro 的快照显示泄露文件在默认分支上的停留时间中位数为 217 天。

数量是 curl 贡献的,能用的凭据是数据库和 SSH

GitGuardian 在约 3,000 次出现中定位每个密钥在文件里的位置:凡能定位的,全部落在 allow 规则或 env 块里,没有一个在 deny 里。数量大头是 curl,占 50%,携带 bearer token、JWT、-u user:pass、Supabase service-role key 和藏在 header 里的 API key;真正能用的凭据却来自数据库和 SSH:PGPASSWORD=、DATABASE_URL= 这类变量前缀只占 15% 的位置,有效率却有 29%;psql、mysql、mongosh、redis-cli 占 4%,有效率 50% 以上;sshpass -p 占 1%,有效率 54%。

具体到密钥类型,settings.local.json 里有 1,955 个不同的有效 Postgres 连接串(对应 5,076 次有效出现)、292 个有效 SSH 密码、116 个有效 MongoDB URI、941 个有效 Google API key、355 个有效 Telegram bot token、142 个有效 Resend key 和 186 个有效 DeepSeek key。按家族分,数据库类凭据是有效密钥中最大的一类,2,280 个;云厂商 token 971 个,AI token 583 个。

同一份数据也解释了扫描器的盲区。Apiiro 测过,gitleaks 和 TruffleHog 加起来会漏掉五分之一的泄露文件——按 iTnews 的数字,1,122 个文件里 gitleaks 标出 564 个、TruffleHog 标出 643 个,215 个从两家手里溜走。在 GitGuardian 的数据里,密码、高熵字符串、JWT、bearer token、用户名密码对这类无厂商格式的通用检测贡献了 63% 的出现次数(71,525 次中的 44,755 次)。PGPASSWORD= 后面跟的那个密码没有任何前缀可供匹配,只认厂商 key 格式的扫描器对这份文件的大部分内容是盲的。

COPY . . 把被 git 忽略的文件带进了 Docker Hub

Apiiro 把 Docker 镜像列为可能的泄露出口但没有实测,GitGuardian 把它量了出来。公开 Docker Hub 镜像里,.claude/settings.local.json 的密钥出现 109,284 次、.claude/settings.json 出现 29,613 次,分布在 543 个镜像仓库的 7,625 个 tag 中;72% 位于 /app、/workspace 或 /usr/src 路径下——整个仓库被一条 COPY . . 拷进了镜像。COPY 拿走的是工作区而不是 git 索引,所以被 git 忽略的文件照样进镜像,除非 .dockerignore 里列出了 .claude/。

去重后是 613 个不同密钥、99 个有效——一个被提交的文件会被重建进每一个 tag。一个有效的 Cloudflare API token 出现在同一个镜像的 559 个 tag 里;一个数据库密码出现在 7 个镜像仓库的 643 个 tag 里。GitGuardian 的结论是:从仓库里删掉文件,对已经推送出去的镜像没有任何作用。

骤降原因仍未查明:博文列出的四种候选解释

快照只能证明文件一直在那里,连续监控才看得到每个月新进了多少。settings.local.json 的泄露从 2025 年 6 月的 256 次起步,当年 10 月单月超过 3,000 次,2026 年 4 月见顶 12,535 次,随后一路下行:6 月 5,276 次、8 月 1,916 次、10 月 959 次,比峰值低 92%。settings.json 的曲线形状相同、滞后一个月:5 月见顶 3,084 次,到 10 月下降 84%。

至于骤降的原因,博文作者坦言不知道。候选解释有四种:Claude Code 改动了权限提示或 ignore 处理、用户增长见顶、GitHub push protection 生效、GitGuardian 自身的检测覆盖变化。作者承认自家一侧尚未排除完毕,「其余的要问 Anthropic」。

不止一个文件:CLAUDE.md 有效密钥率最高,Codex 的 auth.json 也在泄密

同一次统计扫到了 Claude Code 周边的其他文件。团队有意提交的共享文件 .claude/settings.json 含 8,271 个不同密钥,分布在 6,839 个仓库,1,283 个有效;它多了一条泄露路径——约四分之一的泄露版本带有 env 块,把 Claude Code 指向 DeepSeek、OpenRouter、Z.ai、MiniMax、阿里 DashScope、Kimi、Moonshot 等 Anthropic 兼容网关,泄露的是网关凭据:settings.json 里有 205 个有效 DeepSeek key、62 个有效 OpenRouter key、50 个有效 MiniMax key。真正的 Anthropic API key 反而少见:settings.local.json 里只有 139 个不同、28 个有效。

CLAUDE.md 含 6,155 个不同密钥、2,537 个有效,是此次查看的所有文件中有效率最高的——开发者把真实连接串直接粘进了给 agent(AI 编码代理)的指令。.claude/.credentials.json 是 agent 自己登录 Anthropic 的 OAuth 凭据,存放在用户主目录里,出现在 371 个仓库、含 1,366 个不同 token:整个主目录被提交了上去。Codex 有同样的问题:.codex/auth.json 在 536 个仓库里泄出 1,064 个 token。

放到整个 agent 生态看,Apiiro 对比过 16 家 agent 的文档,Claude Code 是其中唯一一个默认把完整已批准命令写进项目文件的;GitGuardian 数了 30 家 agent 的配置文件,全部在泄露,路径也一致——env 块里带 API key 的 MCP server 定义。只是按检测器类型分布判断,只有 .claude/settings.local.json 以「敲进命令的凭据」为主——那正是权限批准被持久化之后的形状。

Anthropic 称正在研究,GitGuardian 用数据回应「手动创建」的说法

据 报道,Anthropic Claude Code 负责人 Boris Cherny 11 月 7 日在 回应:Claude Code 历来没有做过密钥清洗(这方面有很多现成的好工具),「但我们正在研究能做些什么来防止它」。他说团队打算把「让 auto 模式拦下这类命令」「内置基础密钥扫描」等思路做成原型,权衡清楚后再决定是否发布,并坦言这些办法可能解决不了全部问题。他强调 .claude/settings.local.json 本意就是留在本地,Claude 创建该文件时会自动写入 gitignore,因此这次暴露的副本是用户手动创建并提交的;他建议用 auto 模式取代权限规则,并开启 GitHub 等托管平台自带的密钥扫描。当读者指出同样的暴露在 auto 模式下也可能发生时,他回复「确实,发现得好」。

GitGuardian 在同一篇博文里用数据回应了这套说法。文件内容不是手敲的:检查过的约 3,000 次出现中,每个密钥都落在与权限提示所写形状完全一致的 allow 规则里;63% 的发现是没有任何厂商格式的密码和 token;GitHub 上被吊销的密钥,在 Docker Hub 的镜像里还留着副本。

谁在提交:个人邮箱最多,机构中教育行业居首

GitGuardian 按提交者邮箱域名给两个文件的每次出现做了分类。个人邮箱服务对应 15,993 个不同密钥、4,270 个有效;GitHub noreply 地址贡献 3,084 个(773 个有效);3,338 个企业或自建域名对应 5,924 个(1,499 个有效);266 个学术域名对应 426 个(103 个有效)。把企业域名与公司记录匹配后得到 417 家机构的行业分布:教育和研究以 172 家机构、75 个有效凭据居首,软件与 IT 服务以 141 家、69 个紧随其后,两者合计约占四分之三;其余是长尾——电信 15 家、零售 13 家、金融保险 11 家、媒体与营销 10 家、工业与建筑 10 家、医疗 5 家(4 个有效凭据)、政府和防务 4 家。博文提醒,这个样本偏向 GitGuardian 有记录的公司,看排名即可,别看绝对数。

还有一个与提交者有关的数据点:263 个仓库的泄露提交,git 作者地址是 Claude 的 noreply 地址——GitGuardian 判断这类提交由 Claude Code 或其 GitHub action 代用户完成,涉及 406 个不同密钥、107 个有效。Apiiro 观察到同一模式的另一个形态:1,105 个仓库中有 539 个的提交带有 Claude 的联合署名标记(co-author trailer)。

修复从轮换开始,因为镜像和 fork 不会跟着删除

GitGuardian 给出的修复顺序很明确:先轮换文件里出现过的所有凭据,再谈清理——git 历史、fork 和 Docker Hub 镜像都留着副本,改写历史够不到它们。之后把 .claude/ 加进仓库自己的 .gitignore 和 .dockerignore,打开文件或运行 /permissions 删掉所有含密钥的规则。往后写命令时用 $N8N_API_KEY 这样的变量引用密钥:allow 规则存的是字面字符串,写变量名就只记录名字、不记录值——不过若 shell 回显了变量值,它仍会进入会话记录。批准规则时用窄前缀,比如 Bash(curl -H "X-N8N-API-KEY: $N8N_API_KEY" https://n8n.example.internal:*),而不是会放行任何 curl 的 Bash(curl:*)——后者连提示注入写出的命令也会一起放行。

对安全团队,GitGuardian 的建议是把 .claude/、.cursor/、.gemini/、.codex/、.mcp.json 和 CLAUDE.md 当作和 .env 一样会带密钥的文件,在 pre-commit(提交前钩子)、CI(持续集成)、git 历史和容器镜像仓库里都扫一遍,并确认扫描器能抓到藏在命令里的密码而不只是厂商 key 格式。给 Anthropic 的建议落在工具本身:不要把含 VAR=value 前缀、header 值、URL 用户信息或密码参数的整条命令持久化成精确匹配规则,改为提供仅本次会话有效的批准选项。

参考链接

More from this developing story

  • Apiiro 报告:Claude Code「Yes, and don't ask again」把含密码的完整命令明文写入设置文件,公开 GitHub 扫出 1,379 个密钥Nov 8, 2026
  • GitGuardian 独立复核 Claude Code 密钥泄露:公开 GitHub 23,276 个仓库含 31,088 个密钥、17% 检测时仍有效,Docker Hub 镜像另涉 613 个Nov 9, 2026