Claude Code 授权规则可能留下明文密钥
文章指出,Claude Code 的持续授权规则可能将含凭据的命令原样写入本地配置,随后随仓库公开。其引用的调查在 1122 份公开配置中发现秘密信息,其中 215 份未被两款常见扫描器检出。
AI 深度解读
点一次 Claude Code 的「Yes, and don't ask again」,可能会把命令里的数据库密码一并保存进项目文件。原文追踪的泄露路径很具体:批准命令、持久化权限、配置进入 Git,最后出现在公开仓库里。
据原文转述,Apiiro 在 104,185 份本地配置中发现 1,122 份含有秘密,其中 215 份没有被两款扫描器中的任何一款标记。对程序员最有用的提醒是:AI 工具保存的权限配置,也需要像 .env 一样管理。
一次「不再询问」,究竟保存了什么
假设你让 Claude Code 查测试数据库,它生成了一条带有 PGPASSWORD= 的 psql 命令。如果密码直接写在命令里,选择永久批准后,保存下来的权限规则也可能包含这个密码。
按原文引用的文档,这类 Bash 授权会按仓库和命令永久保留,写入仓库根目录的 .claude/settings.local.json,后续会话以及该仓库的 worktree 都会使用它。
关键区别在于批准的对象。有时界面提供的是 npm test * 这样的模式;有时保存的是完整命令。后者如果带有密码,权限配置就同时成了凭据存储。

原文称,研究人员使用当时最新的 Opus 5.5 和 Fable 5.1 复现了问题。这是原文报告的模型名称和状态,不能据此推断其他版本的表现。他们比较了 16 个 coding agent 的文档,只有 Claude Code 被确认默认把完整获批命令存进项目文件;这个结论也不等于其余工具都没有泄露风险。
原文还提到,2025 年 8 月已有相关缺陷报告。issue #5544 在 2026 年 1 月 3 日被机器人以「not planned」关闭,附带的理由是连续 60 天没有活动。这能说明工单状态,不能单凭它判断产品团队是否做过其他处理;原文引用的两家媒体均未报道 Anthropic 的回应。
文件叫 local,为什么还会进入公开仓库
问题出在忽略规则的作用范围。
Claude Code 首次写入该文件时,如果仓库尚未忽略它,会把 **/.claude/settings.local.json 加入全局 Git 忽略文件,也就是 core.excludesFile 指定的位置,默认是 ~/.config/git/ignore。
全局配置只保护当前机器。它不会随仓库传给同事、CI 或新电脑。手动创建配置文件时,文档还要求使用者自行补充 .gitignore。更关键的是,已经被 Git 跟踪的文件不会因为新增忽略规则而退出版本管理。
文件名里的 local,不是版本控制的安全边界。
据原文转述,在研究者追踪的 1,105 个仓库中,539 个出现过修改该文件、且将 Claude 列为共同作者的提交。这说明配置进入提交的路径需要审查,但共同作者信息不足以独立证明每次提交都是 agent 自主完成的。
团队主动共享的 .claude/settings.json 也在调查范围内:76,011 份公开副本中,298 份含有秘密。原文引用的文档说,VS Code 扩展允许在批准卡片上选择规则保存到哪个文件,包括共享配置;CLI 的交互批准则只写入本地文件。
所以,检查不能停留在「有没有忽略 local 文件」,还要看共享规则究竟保存了哪些参数。
扫描器为什么漏掉命令里的密码
Apiiro 检查了 103,617 个公开仓库中的 104,185 份本地配置,发现 1,122 份至少含有一个秘密,共计 1,379 个不同秘密。两款扫描器中,gitleaks 标记了 564 份,TruffleHog 标记了 643 份,另有 215 份两者都没标记。这些数字按文件计数,不能相加当作秘密总量。
原文列出的类型包括 379 个数据库密码、43 项面向公网服务器的 SSH 登录凭据、42 个 GitHub、GitLab 和 npm token,以及 23 个 AWS key。GBHackers 另列出 122 个 Supabase service-role key。受影响文件涉及 63 家组织,多数是不同规模的软件公司。
为什么带密码的命令容易漏?AWS key 或部分平台 token 有固定前缀、长度和结构,扫描器比较容易识别。普通密码没有统一外形,藏在 PGPASSWORD=、sshpass -p 或 mysql -p 后面时,需要结合命令上下文判断。

这里也有证据边界。研究者通过已知密钥格式,或「密码、token 与公网服务器地址相邻,再经 AI 审核」来认定秘密,没有测试这些凭据是否仍然有效。只有一家收到通知的公司确认,其密钥当时仍然有效。两款扫描器运行时也都没有启用验证步骤,因此这不是完整的产品能力对比。
泄露范围还会沿 Git 扩散:历史版本在 509 个仓库中额外留下 734 个秘密,74 个仓库的 211 个 fork 也保留了相同秘密。把共享配置、历史和 agent 聊天日志纳入后,原文给出的总量是 1,994 个仓库、2,539 个秘密。这个口径比本地配置扫描更大,不能混着比较。
我的判断
我认同原文对风险链路的判断:为了减少弹窗而保存的命令,可能带入原本只打算临时使用的凭据;机器上的忽略配置,又容易让团队误以为仓库已经获得保护。
但「215 份漏检」不能直接推出扫描器不可靠。研究没有提供足够的扫描配置、规则覆盖及验证对照,也没有证明全部秘密仍然有效。它更有力地说明了:固定格式扫描需要补充命令上下文检查。
用变量替换字面量也有明确边界。PGPASSWORD="$DB_PASSWORD" psql ... 能让这条获批命令保存变量名,而不是密码值,但原文没有证明它能覆盖日志、其他命令或全部执行路径。它解决的是这条持久化路径上的问题。
同样,批准命令模式可以减少重复授权,却要控制范围。原文的 .env deny 示例针对 Claude 的文件读取工具,不能把它理解为所有进程都无法读取 .env。权限模式、仓库忽略规则和秘密扫描各有作用,不能相互替代。
能拿来做什么
-
先查文件是否被跟踪,再查它是否进过历史。 在使用过 Claude Code 的仓库执行下面三条命令,分别确认当前状态、历史记录和忽略规则来源:
# 当前是否跟踪了该文件? git ls-files .claude/settings.local.json # 是否曾在任意分支提交过? git log --all --oneline -- .claude/settings.local.json # 当前由哪条忽略规则覆盖? git check-ignore -v .claude/settings.local.json注意最后一条:没有输出,可能是未配置忽略规则,也可能是文件已经被跟踪,不能直接认定安全。
-
对完整历史执行秘密扫描。原文给出的命令是
gitleaks git -v,适用于 gitleaks 8.19+;旧版本使用gitleaks detect -v,也可运行trufflehog git file://.。再用git log --all -p -- .claude/ | grep -nE 'PGPASSWORD=|sshpass -p|mysql .*-p'补查命令里的密码形态。发现公开凭据后,先轮换,再清理;删除当前文件或重写历史,都不能让 fork 中的副本失效。 -
将本地配置的忽略规则提交到仓库,并检查已有授权。已跟踪的文件可先执行
git rm --cached .claude/settings.local.json,再把.claude/settings.local.json加入.gitignore。运行/permissions查看规则及来源,删除带秘密的规则,包括从未提交过的副本。团队还可在 pre-commit 和 CI 中检查.claude/、.cursor/、.gemini/、.specstory/,并安排历史扫描。 -
给前端、Node 项目的常用任务配置不含秘密的授权模式,数据库凭据通过秘密管理系统注入变量。原文提供的配置示例如下:
{ "permissions": { "allow": ["Bash(npm run test *)"], "deny": ["Read(./.env)", "Read(./.env.*)"] } }注意
allow那一行保存的是命令模式;两条deny则限制文件工具读取.env,不要把它们当成完整的凭据隔离机制。