Claude Code 密钥泄露:分析 .claude/settings.local.json 泄露事件
泄露机制
Claude Code 的“不再询问”(Don't Ask Again) 功能旨在通过缓存 shell 命令的权限规则来简化开发人员的工作流程。当用户批准包含敏感信息(如数据库密码、API 令牌或云密钥)的命令时,代理会将完整的命令字符串保存到项目目录下的 .claude/settings.local.json 文件中。由于该文件位于项目文件夹内,它经常会被无意中提交到版本控制系统中,如果仓库被推送到公共 GitHub 主机,这些密钥就会变得公开可访问。
虽然 Claude Code 尝试将此文件添加到全局 gitignore 列表中,但在文件夹在文件创建后才成为仓库、文件被克隆到新机器或开发人员手动将文件添加到仓库等场景下,这种保护措施会失效。Apiiro 的研究表明,在 1,105 个包含真实密钥的仓库中,有 539 个仓库的提交是由代理本身共同完成的,这实际上实现了泄露的自动化。
范围与影响
Apiiro 在 1,994 个公共 GitHub 仓库中识别出了 2,539 个真实密钥。其中包括生产数据库密码、云 API 密钥和 SSH root 登录凭据等高价值凭据。影响范围涵盖 63 个组织,包括初创公司、软件代理商和 IT 服务公司。在一个案例中,某数据库供应商自身的管理员级云密钥被泄露。
除了 GitHub,风险还延伸到了开发人员的工作站。由于 .claude/settings.local.json 文件以纯文本形式存储,它成为了恶意软件的主要目标。安全研究人员指出,现有的凭据窃取蠕虫(如 Shai-Hulud npm 蠕虫)已经开始扫描本地环境以查找此类配置文件。
当前密钥扫描器的局限性
像 Gitleaks 和 TruffleHog 这样的标准密钥扫描工具往往无法检测到这些泄露,因为它们主要针对识别特定的密钥格式(例如带有提供商前缀的字符串)。Claude Code 捕获的许多密钥是直接嵌入到命令行参数中的密码(例如 PGPASSWORD=... 或 sshpass -p ...)。对于传统扫描器而言,这些看起来像是普通文本,从而导致了严重的检测缺口。Apiiro 发现,五分之一的受损文件既没有被 Gitleaks 标记,也没有被 TruffleHog 标记。
缓解措施与最佳实践
为了保护环境免受此类泄露的影响,开发人员和安全团队应采取以下做法:
- 取消跟踪并忽略: 使用
git rm --cached .claude/settings.local.json立即从 git 跟踪中移除.claude/settings.local.json,并确保将其添加到项目的.gitignore文件中。 - 凭据轮换: 如果包含密钥的文件已被提交,请假定这些凭据已泄露。轮换文件历史记录中发现的所有密钥、令牌和密码。
- 使用环境变量: 切勿将密钥直接输入命令。通过环境变量(例如
$DB_URL)引用它们,以便缓存的命令字符串仅包含变量名,而不是原始密钥。 - 增强扫描: 配置 CI/CD 流水线和预提交钩子 (pre-commit hooks) 以扫描标准密钥格式之外的模式,特别是查找“命令中包含密码”的模式。
- 代理沙箱化: 考虑在隔离环境中运行代理,或使用限制代理执行未经授权的写操作或访问敏感服务能力的 API 代理。
社区见解
开发人员之间的讨论强调,虽然工具的行为是一个促成因素,但根本原因通常是缺乏严格的安全卫生习惯。评论者指出:
"根本问题不在于那个按钮,而在于允许列表存储了完整的命令字符串……密钥应该仅通过环境变量进入命令,且 .claude/ 应该放在机器范围的全局 gitignore 中,而不是仓库里。" — @handle
其他人强调,在没有手动验证提交内容的情况下依赖自动化工具是一种危险的做法。正如一位用户所指出的:“你需要对自己负责,永远不要依赖某些机器人自动化……在把东西放到每个人都能永远看到的地方之前,先读一读它们。”
Sources
相关
- Dispatch
- 项目
- Dispatch
- 项目
- 项目