Undercover 模式:Anthropic 员工的“防泄密”护盾
一句话讲清楚
Undercover(潜伏)模式是 Claude Code 为 Anthropic 内部员工设计的一种安全机制。当员工在公共仓库(Public Repo)中使用 Claude Code 时,该模式会自动激活。它会严厉限制模型在生成的 Commit Message 或 PR 描述中包含任何 Anthropic 内部代号(如 Capybara, Tengu)、内部 Slack 频道或未公开的模型版本号。
实现细节
这不是一个简单的标志位,而是一套深植于代码中的自动化防线:
- 自动识别与触发:系统维护了一个包含约 75 个内部仓库的允许列表(
INTERNAL_MODEL_REPOS),其中包括anthropics/anthropic和claude-cli-internal。- 触发逻辑:当检测到当前 Git 远程仓库不在列表中时,自动激活 Undercover 模式。
- 安全默认值:如果无法确定(例如在没有 Git 的临时目录下运行),则默认开启潜伏模式,以宁可错杀、绝不泄密的姿态运行。
- 严厉的指令注入:一旦激活,
getUndercoverInstructions会向系统提示词(System Prompt)中注入一段“CRITICAL”级别的指令。- 禁止项:严禁提及动物代号(Capybara, Tengu)、具体版本号(Opus 4.7)、Go 链接、内部仓库名。
- 伪装要求:甚至禁止模型自称 AI,要求它像一个普通的“人类开发者”一样写提交信息。
- 身份剥离(Attribution Stripping):在 Undercover 模式下,Claude Code 会强制移除所有可能暴露其 AI 身份的 Git 尾注(Trailers),如
Co-Authored-By归属信息。 - 死代码消除(Dead-Code Elimination):
- 源码中所有关于潜伏模式的逻辑都被包裹在
process.env.USER_TYPE === 'ant'的条件分支中。 - 外部版本透明:由于
USER_TYPE是构建时的常量,打包工具(Bundler)在生成面向普通用户的版本时,会直接通过 Tree-shaking 彻底剔除这些代码路径。你拿到的 Claude Code 里甚至不存在这段逻辑,这既保护了代码整洁,也避免了外部用户窥探内部仓库列表。
- 源码中所有关于潜伏模式的逻辑都被包裹在
- 强制性与不可逆性:源码明确注释:“There is NO force-OFF switch”(没有强制关闭开关)。只要自动化检测没过,员工就必须在潜伏模式下工作。
实战注意事项
- 单向透明:这套机制的存在揭示了一个事实:Anthropic 的工程师们已经在大规模使用 Claude Code 开发他们的所有项目,包括那些面向公众的开源项目,但他们对安全性有着极高的警惕。
- 强制覆盖:即使在内部仓库,员工也可以通过环境变量
CLAUDE_CODE_UNDERCOVER=1强制开启此模式,作为双重保险。 - 外部用户的隐身:对普通开源用户来说,你永远不会看到这个模式的对话框或提示词注入,因为它在编译阶段就已经消失了。
延伸阅读
- 去翻翻
src/utils/commitAttribution.ts,那里藏着那 75 个神秘的内部仓库名单(尽管很多你可能没听说过)。 - 如果你对 Git 提交信息的归属统计感兴趣,可以研究
calculateCommitAttribution。
源码锚点
src/utils/undercover.ts:控制潜伏模式的核心开关和指令注入内容。
📄 src/utils/undercover.ts — 控制潜伏模式的核心开关和指令注入内容。
typescript
export function isUndercover(): boolean {
if (process.env.USER_TYPE === 'ant') {
if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return true
// Auto: active unless we've positively confirmed we're in an allowlisted
// internal repo. 'external', 'none', and null (check not yet run) all
// resolve to ON. The check is primed in setup.ts; only 'internal' → OFF.
return getRepoClassCached() !== 'internal'
}
return false
}src/utils/commitAttribution.ts:定义了内部仓库白名单INTERNAL_MODEL_REPOS。
📄 src/utils/commitAttribution.ts — 定义了内部仓库白名单 `INTERNAL_MODEL_REPOS`。
typescript
const INTERNAL_MODEL_REPOS = [
'github.com:anthropics/claude-cli-internal',
'github.com/anthropics/claude-cli-internal',
'github.com:anthropics/anthropic',
'github.com/anthropics/anthropic',
'github.com:anthropics/apps',
'github.com/anthropics/apps',
'github.com:anthropics/casino',
'github.com/anthropics/casino',
'github.com:anthropics/dbt',
'github.com/anthropics/dbt',
'github.com:anthropics/dotfiles',
'github.com/anthropics/dotfiles',
'github.com:anthropics/terraform-config',
'github.com/anthropics/terraform-config',
'github.com:anthropics/hex-export',
'github.com/anthropics/hex-export',
'github.com:anthropics/feedback-v2',
'github.com/anthropics/feedback-v2',
'github.com:anthropics/labs',
'github.com/anthropics/labs',
'github.com:anthropics/argo-rollouts',
'github.com/anthropics/argo-rollouts',
'github.com:anthropics/starling-configs',
'github.com/anthropics/starling-configs',
'github.com:anthropics/ts-tools',
'github.com/anthropics/ts-tools',
'github.com:anthropics/ts-capsules',
'github.com/anthropics/ts-capsules',
'github.com:anthropics/feldspar-testing',