[控场AI]
· 8 分钟阅读· 4,139 字

GitHub默认拦截Anthropic密钥推送,但私库仍未覆盖

GitHub默认拦截Anthropic密钥推送,但私库仍未覆盖

GitHub secret scanning 新增 Anthropic 密钥默认推送拦截,但仅覆盖公开仓库且可被绕过。

GitHub secret scanning 新增了 `anthropic_user_api_key` 和 `anthropic_service_api_key` 两种检测器,并将它们加入默认推送保护拦截名单,公开免费仓库也会被覆盖。这是一次实打实的改进,但范围有限:默认设置下的私有仓库不会触发拦截,需要管理员手动启用 GitHub Secret Protection 和仓库级推送保护。绕过机制也存在——任何有写权限的人都能指定理由绕过,且在仅有默认推送保护时不会生成告警。Anthropic 建议 Agent 和 CI 使用可独立吊销的服务账号密钥。文中还提醒,拦截只挡住 GitHub,密钥仍留在本地 commit 和 shell 历史中,泄露后应先轮换密钥。

当你的编码 Agent 完成任务、用 git add -A 暂存所有改动并推送时,commit 里可能夹着一个带 Anthropic API key 的 .env 文件。GitHub 的 secret scanning 现在能识别更多这类密钥,并在推送阶段直接拦截。

根据 GitHub 官方 changelog,secret scanning 新增了两种 Anthropic 密钥检测类型:anthropic_user_api_key 和 anthropic_service_api_key,且推送保护(push protection)默认拦截这两类密钥。在启用了 secret scanning 的仓库中,包含这些密钥的 commit 会被自动阻止,公开的免费仓库也包含在内。

这确实是一次实打实的改进。但它比听起来要窄——默认设置下的私有仓库,依然不会触发拦截。

GitHub 默认拦截 Anthropic 密钥推送

这次更新具体改了什么

同一则 changelog 把三件事打包在一起:

  • 新增两个 Anthropic 检测器 anthropic_user_api_key、anthropic_service_api_key,以及一个 Cloudsmith API key 检测器。
  • Salesforce 加入 secret scanning 合作伙伴,用于检测 Marketing Cloud 的 OAuth2 token。在公开仓库中发现的合作伙伴密钥会发送给签发方,由其吊销或轮换。
  • 两类新的 Anthropic 密钥被加入默认推送保护拦截名单。

该条目还说明,只要开启了 secret scanning,公开或私有仓库都会收到相应的告警。

Anthropic 并非这个项目的新面孔。GitHub 早在 2024 年 8 月就宣布 Anthropic 成为 secret scanning 合作伙伴,其支持的密钥模式表中还列出了 anthropic_api_key、anthropic_admin_api_key 和 anthropic_session_id。当密钥真的落入公开仓库时,Anthropic 的密钥安全文档写道:"Anthropic 会自动停用暴露的 API key",并邮件通知受影响的用户。

为什么是这两种密钥类型

这两个检测器的命名,对应了 Anthropic 现在创建密钥的方式。其 API key 文档要求你在创建时先选类型:个人密钥(personal key)"以你的身份运行,如果你离开组织就会失效";服务账号密钥(service account key)则面向"CI 流水线、生产服务或 Agent 等工作负载"。文档用一句话总结:"自己的开发用个人密钥,任何共享的东西用服务账号密钥。"

旧的 workspace key 被描述为"没有所有者的遗留密钥",创建者离开后仍会继续生效。

GitHub 的模式表把两个检测器称为"Anthropic User API Key"和"Anthropic Service Account API Key"。把"user"对应到 Anthropic 所说的个人密钥,是原文作者的推断——双方都没有明确说明。

这一区分对 Agent 场景尤其关键:Agent 通常代表某个共享角色执行任务,用服务账号密钥可以独立吊销,不会牵动个人密钥。

Workspace key 是 Anthropic 早期控制台中的一种密钥形态,在个人密钥与服务账号密钥的二分体系上线之前使用。它的特殊性在于没有绑定到某个具体成员账号:创建者离职后密钥仍然有效,也没有清晰的归属人。这意味着密钥暴露后难以从「谁该负责轮换」的角度追责,同时权限治理也更模糊。Anthropic 将其归为遗留类型,并推动用户迁移到新的个人/服务账号模型,本质上是把「无主密钥」变成「有主密钥」,让吊销和审计有明确的责任边界。

拦截到底做了什么,谁能放行

根据 GitHub 推送保护文档,它覆盖这些场景:命令行推送、GitHub UI 中创建的 commit、文件上传、REST API 请求,以及仅限公开仓库的 GitHub MCP server 交互。最后一条值得注意——如果你的 Agent 通过 GitHub MCP server 而不是 git 写入 GitHub,这一段同样受保护范围约束。

拦截并非铜墙铁壁。文档说明,默认情况下"任何拥有仓库写权限的人都可以通过指定绕过原因来绕过推送保护"。开启仓库级推送保护后,你选择的原因决定了告警的结局:

  • "用于测试"——告警以"用于测试"关闭。
  • "误报"——以"误报"关闭。
  • "稍后修复"——告警保持打开。

在这种模式下,每次绕过都会写入审计日志,并邮件通知关注该仓库的所有者、安全管理员和仓库管理员。但如果只有面向用户的默认推送保护,文档说它"在你绕过推送保护时不会生成告警",除非同时在仓库级别启用了推送保护。也就是说,默认设置的公开仓库上,一次绕过可能不会留下任何供人复查的告警。

你的 Agent 通常用你的 git 凭证推送,所以能放行被拦密钥的人就是你,或者任何使用这些凭证的东西。在开启仓库级推送保护的场景,关闭来自 Agent 分支的告警前,请先看清绕过原因。

还有一点:拦截意味着密钥已经存在于某个本地 commit 中。推送保护只是把它挡在了 GitHub 之外,并没有从你的分支里删除它。

Schema 中的 key type 字段决定 GitHub 模式匹配的目标。GitHub 的 secret scanning 依赖签发方提供的正则与校验规则,每种检测器对应一类特定的字符串结构。anthropic_user_api_key 和 anthropic_service_account_api_key 之所以能被区分,是因为 Anthropic 在密钥前缀或内部结构中编码了类型信息,GitHub 只需分别匹配即可。这也解释了为什么旧的 anthropic_api_key、anthropic_admin_api_key、anthropic_session_id 能同时共存——它们对应 Anthropic 历史上不同用途、不同时期签发的密钥格式。

没被覆盖的地方

推送保护文档描述了两类,覆盖的仓库并不相同:

  • 面向用户的推送保护:"默认启用","阻止你向 GitHub 上的公开仓库推送密钥"。文档没有说它覆盖私有仓库。
  • 面向仓库的推送保护:"需要启用 GitHub Secret Protection",且"默认禁用"。必须由管理员、所有者或安全管理员手动开启。

也就是说,对于一个没人启用 Secret Protection 和仓库级推送保护的私有仓库,文档描述中不存在任何拦截。这次更新只是把默认名单变长了,并没有在原本关闭的地方把功能打开。

Git 也不是密钥唯一以明文存在的地方。如果你曾在终端里敲过 export ANTHROPIC_API_KEY=...,它就留在你的 shell 历史里。原文作者在文中提到自己正在开发 Hermes IDE,其 2.3.2 版本不再为包含 API key、token 或密码的命令提供终端建议,但 shell 自身的历史文件保持不变,清理仍需你自己动手。Hermes 与 GitHub、Anthropic 无隶属关系。

Shell 历史文件(如 .bash_history、.zsh_history)在默认配置下会记录每条交互执行的命令,包括 export ANTHROPIC_API_KEY=sk-ant-... 这样的赋值语句。与 .env 不同,这些历史文件通常位于用户主目录,不会被 git status 或 secret scanning 感知。清理方式因 shell 而异:可以 history -c 清空当前会话、手动删除历史文件中匹配行,或设置 HISTIGNORE、HISTCONTROL=ignorespace 避免敏感命令被记录。更彻底的做法是把密钥写入 shell 的 rc 文件由启动时读取,而不是每次手动 export。

这周可以做的三件事

1. 尽可能开启仓库级推送保护。 如果组织有 GitHub Secret Protection,在组织级别启用推送保护。按文档说法,没人动手它就会一直关着。

2. 给 Agent 和 CI 配独立密钥。 Anthropic 文档建议对"任何共享的东西"使用服务账号密钥,Agent 正在其列。独立密钥意味着泄露的 Agent 密钥可以单独吊销,不牵动你自己的密钥;而个人密钥会在所有者离开组织时失效。

3. 把 .env 挡在版本树之外,并检查已经进去的东西。

# 停止跟踪该文件但保留在磁盘上
echo ".env" >> .gitignore
git rm --cached .env

# 统计历史中形似 Anthropic 密钥的行数
git log --all -p | grep -c 'sk-ant-'

Anthropic 文档说每个密钥"都以 sk-ant- 开头",这正是 grep 要找的模式。如果 .env 从未被跟踪,git rm --cached 会无害报错。计数包含占位符和已删除的行,动手前先查看匹配内容。如果出现真实密钥且该分支曾被推送过,请在 Claude Console 中轮换它。先轮换——历史重写无法召回一个已经被别人复制走的密钥。

把 GitHub 的拦截当作上面三步之下的安全网,而不是替代方案。

#GitHub secret scanning#Anthropic API key#推送保护#API 密钥泄露#Claude API#Secret Protection#AI 编程安全
分享:

相关推荐