基于 @anthropic-ai/claude-code@2.1.88 逆向还原源码的全面审视
摘要
本文基于对 Claude Code v2.1.88 客户端逆向还原代码的系统性梳理,从身份追踪体系、风控机制设计、遥测管线架构与隐私控制面四个维度进行深度分析。核心发现是:Claude Code 构建了一套多层级、多链路、高冗余的用户/设备/会话关联体系,其设计远超简单的”产品分析”需求,呈现出工业级风控基础设施的特征。
1. 架构概览:三层身份锚定模型
graph TD subgraph Layer1["🔑 第一层:账号身份(Account Identity)"] AUTH["Authorization / x-api-key"] ACCT["account_uuid"] ORG["organization_uuid"] EMAIL["email"] end subgraph Layer2["💻 第二层:设备身份(Device Identity)"] DID["device_id"] UID["user.id (OTel)"] GBID["GrowthBook id / deviceID"] DDBUCKET["Datadog userBucket"] end subgraph Layer3["🔄 第三层:会话身份(Session Identity)"] SID["session_id"] XSID["X-Claude-Code-Session-Id"] GBSID["GrowthBook sessionId"] OTELSID["OTel session.id"] end PERSIST["getOrCreateUserID()"] --> DID PERSIST --> UID PERSIST --> GBID PERSIST -.->|SHA256 slice| DDBUCKET OAUTH["getOauthAccountInfo()"] --> ACCT OAUTH --> ORG OAUTH --> EMAIL SESSINIT["getSessionId() → randomUUID()"] --> SID SESSINIT --> XSID SESSINIT --> GBSID SESSINIT --> OTELSID style Layer1 fill:#1a1a2e,stroke:#e94560,color:#eee style Layer2 fill:#1a1a2e,stroke:#0f3460,color:#eee style Layer3 fill:#1a1a2e,stroke:#16213e,color:#eee
核心洞察
Claude Code 的身份追踪不是”一个 ID 打天下”,而是构建了三层正交锚定:
| 层级 | 稳定性 | 粒度 | 可关闭性 |
|---|---|---|---|
| 账号层 | 跨设备稳定 | 最粗(同一人的所有设备) | ❌ 认证不可关闭 |
| 设备层 | 跨重启稳定 | 中(单台设备) | ❌ 无字段级开关 |
| 会话层 | 单次运行内稳定 | 最细(一次交互流程) | ❌ 无字段级开关 |
这种设计的含义是:即使用户切换了账号,设备层 ID 仍然可以将不同账号关联到同一物理设备;即使用户更换了设备,账号层 ID 仍然可以将不同设备关联到同一用户。
2. 同源关系深度解剖
2.1 最关键的同源链条
逆向代码揭示的一个核心架构特征是字段同源复用——表面上看起来独立的十几个字段,实际上只有少数几个”源头”。
flowchart LR subgraph Source["源头"] S1["getOrCreateUserID()"] S2["getOauthAccountInfo()"] S3["getSessionId()"] S4["getAttributionHeader()"] S5["getUserAgent()"] end subgraph Sinks["上传终点"] S1 --> D1["device_id"] S1 --> D2["metadata.user_id.device_id"] S1 --> D3["GrowthBook id/deviceID"] S1 --> D4["OTel user.id"] S1 -.->|SHA256 truncate| D5["Datadog userBucket"] S2 --> A1["account_uuid"] S2 --> A2["organization_uuid"] S2 --> A3["email"] S2 --> A4["OTel user.account_uuid"] S2 --> A5["GrowthBook accountUUID/orgUUID"] S2 --> A6["OTel organization.id"] S3 --> SE1["session_id"] S3 --> SE2["X-Claude-Code-Session-Id"] S3 --> SE3["GrowthBook sessionId"] S3 --> SE4["OTel session.id"] S3 --> SE5["1P event session_id"] S4 --> AT1["x-anthropic-billing-header"] S4 --> AT2["cc_version / cc_entrypoint"] S4 --> AT3["cc_workload"] S4 --> AT4["cch attestation"] S5 --> UA1["User-Agent"] S5 --> UA2["x-app"] S5 --> UA3["x-client-app"] end style Source fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 style Sinks fill:#0d1117,stroke:#3fb950,color:#c9d1d9
2.2 这意味着什么
[!IMPORTANT]
同源复用意味着服务端可以通过任何一条上报链路获得完整的用户画像关联。即使某些遥测链路被关闭,主请求中携带的认证信息和会话头已经足以完成身份锚定。
从工程视角看,这种冗余有两种可能解释:
- 防御性工程:不同团队(API、Analytics、Infra)各自需要独立可靠的用户关联键,同源是自然结果
- 刻意冗余:确保即使在部分链路失败或被关闭的情况下,仍有足够的信号完成用户关联
实际情况很可能是两者兼具。
3. 风控机制的四层防线
3.1 防线架构
graph TB subgraph Line1["🛡️ 第一防线:客户端真伪校验"] CCH["cch attestation<br/>服务端验证令牌"] BILLING["x-anthropic-billing-header<br/>归因文本块"] UA["User-Agent<br/>客户端画像串"] end subgraph Line2["🔍 第二防线:会话行为关联"] SESS["session_id 链路<br/>跨服务串联"] REQ["x-client-request-id<br/>单请求追踪"] end subgraph Line3["🌍 第三防线:环境异常检测"] REMOTE["remote-container-id<br/>remote-session-id"] ENV["platform / terminal<br/>arch / node_version"] PROXY["apiBaseUrlHost<br/>代理/网关识别"] end subgraph Line4["📊 第四防线:行为画像"] PROJ["project_file_count<br/>项目规模"] TOOLS["MCP tools/servers<br/>工具生态"] MODE["permissionMode<br/>thinkingType"] RH["rh (repo hash)<br/>仓库指纹"] end Line1 --> Line2 --> Line3 --> Line4 style Line1 fill:#1a1a2e,stroke:#e94560,color:#eee style Line2 fill:#1a1a2e,stroke:#f39c12,color:#eee style Line3 fill:#1a1a2e,stroke:#3498db,color:#eee style Line4 fill:#1a1a2e,stroke:#2ecc71,color:#eee
3.2 各层解析
第一防线:客户端真伪校验
这是最硬的一层。代码注释中明确写道:
“server verifies this token to confirm the request came from a real Claude Code client”
cch attestation 令牌是一种客户端证明机制——类似于 Google 的 SafetyNet / Play Integrity,它试图让服务端能够区分”真正的 Claude Code 客户端”和”伪造或修改过的客户端”。
关键技术细节:
cch被包裹在x-anthropic-billing-header整个文本块中,不是独立 HTTP header- 当前版本中使用的是
cch=00000占位值,说明完整的 attestation 机制可能还在建设中 NATIVE_CLIENT_ATTESTATION是 build-time feature flag,非运行时开关
[!WARNING]
cchattestation 虽然目前使用占位值,但其架构已经搭好。一旦 Anthropic 启用真正的远程证明,将极大提升伪造客户端的难度。这是一个值得持续关注的演进方向。
第二防线:会话行为关联
session_id 通过四条独立链路(主 API、1P 事件、GrowthBook、OTel)同步上报,使服务端可以将:
- 主模型请求
- 产品分析事件
- 实验分流记录
- 基础设施遥测数据
全部串联到同一条操作链路。这不仅是调试工具,更是行为序列重建的基础。
第三防线:环境异常检测
通过检测运行环境的异常信号(如非标准代理、远程容器、异常平台组合)来识别潜在的滥用场景。
| 字段 | 检测能力 |
|---|---|
apiBaseUrlHost | 企业代理 / 非标准网关 |
x-claude-remote-container-id | 云端容器环境 |
platform + arch + node_version | 环境指纹一致性 |
rh (repo hash) | 仓库级行为聚合 |
第四防线:行为画像
这是最软的一层,但也最难规避。工具数量、项目规模、使用模式等低分辨率特征,单独看辨识度不高,但组合起来可以构成用户行为指纹。
4. 遥测管线架构:五条独立管线
4.1 管线总览
逆向揭示了 Claude Code 同时维护五条独立的遥测/上报管线,每条有不同的上报目标、开关控制和数据粒度:
flowchart TD CLIENT["Claude Code Client"] CLIENT --> P1["📡 管线 1: 主 API 请求<br/>(messages endpoint)"] CLIENT --> P2["📊 管线 2: 1P 事件日志<br/>(First-Party Event Logger)"] CLIENT --> P3["🧪 管线 3: GrowthBook<br/>(实验分流 + 事件)"] CLIENT --> P4["📈 管线 4: Standard OTel<br/>(Metrics / Logs / Traces)"] CLIENT --> P5["🔬 管线 5: Beta Tracing<br/>(Enhanced Telemetry)"] P1 --> T1["Anthropic API Server"] P2 --> T2["Anthropic 1P Backend"] P3 --> T3["GrowthBook Service"] P4 --> T4["Customer OTLP Endpoint"] P5 --> T5["BETA_TRACING_ENDPOINT"] P2 -.-> DD["Datadog (fanout sink)"] P2 -.-> BQ["BigQuery Metrics"] style P1 fill:#e94560,stroke:#e94560,color:#fff style P2 fill:#f39c12,stroke:#f39c12,color:#fff style P3 fill:#2ecc71,stroke:#2ecc71,color:#fff style P4 fill:#3498db,stroke:#3498db,color:#fff style P5 fill:#9b59b6,stroke:#9b59b6,color:#fff
4.2 管线对比
| 属性 | 主 API | 1P 事件 | GrowthBook | Standard OTel | Beta Tracing |
|---|---|---|---|---|---|
| 核心开关 | 无法关闭 | DISABLE_TELEMETRY | DISABLE_TELEMETRY | CLAUDE_CODE_ENABLE_TELEMETRY | ENABLE_BETA_TRACING_DETAILED |
| 默认状态 | 始终开启 | 开启 | 开启 | 关闭 | 关闭 |
| 携带正文 | ✅ 完整 messages | ❌ metadata 级 | ❌ attribute 级 | 可选(默认关) | ✅ system prompt / tool I/O |
| 携带身份 | ✅ 认证 + 会话 | ✅ device + session + account | ✅ device + session + account | ✅ user.id + session.id | 取决于配置 |
| 服务端控制 | — | GrowthBook killswitch | — | — | GrowthBook allowlist |
| 影响业务 | ✅ 核心功能 | ❌ 分析 | ❌ 实验 | ❌ 可观测性 | ❌ 增强调试 |
4.3 管线独立性的风险含义
[!CAUTION]
五条管线各自有独立的开关体系,且没有统一总开关。这意味着:
- 关闭
DISABLE_TELEMETRY只杀死管线 2 和 3- 关闭
CLAUDE_CODE_ENABLE_TELEMETRY只影响管线 4- 管线 5 (Beta Tracing) 有完全独立的控制路径
- 管线 1 (主 API 请求) 不受任何遥测开关控制
换言之:用户可能以为设置了 DISABLE_TELEMETRY 就”什么都不上传了”,但实际上主请求中的身份信息、会话头、User-Agent 等仍在持续上传。
5. 隐私控制面的不对称性
5.1 可控 vs 不可控字段矩阵
quadrantChart title 字段可控性 vs 身份关联强度 x-axis "低身份关联" --> "高身份关联" y-axis "不可关闭" --> "可关闭" "project_file_count": [0.15, 0.75] "mcp_tools_count": [0.2, 0.7] "userBucket": [0.3, 0.8] "attribution header": [0.45, 0.85] "cch attestation": [0.5, 0.8] "1P event logging": [0.55, 0.75] "GrowthBook events": [0.5, 0.7] "session.id (OTel)": [0.6, 0.65] "User-Agent": [0.4, 0.15] "x-app": [0.35, 0.1] "X-Claude-Code-Session-Id": [0.65, 0.12] "user.id": [0.75, 0.1] "Authorization": [0.95, 0.05] "account_uuid": [0.9, 0.08] "device_id": [0.85, 0.1] "messages body": [0.7, 0.05]
5.2 不对称性分析
从上图可以清晰看到一个倒挂现象:
- 身份关联度最强的字段(认证凭证、设备 ID、账号 UUID)→ 完全不可关闭
- 身份关联度较弱的字段(统计计数、分析事件)→ 有开关可关闭
这种设计是否有意为之,无法从客户端代码中确认。但从效果上看:
用户能关掉的,都不是最关键的;最关键的,用户关不掉。
5.3 fingerprint 的去神秘化
代码中出现的 fingerprint 容易引起不安,但分析显示:
- 它不是硬件指纹(MAC 地址、BIOS 序列号等)
- 它由
首条用户消息片段 + 版本号 + 盐值生成 - 更像是一种请求去重 / 归因签名
代码中同时确认未发现以下采集:
- MAC 地址
- 主板序列号 / BIOS 序列号
- 机器 UUID / 网卡硬件标识
- 传统意义上的硬件指纹 SDK
6. 环境变量开关的三种判定陷阱
6.1 三种不同的”真值判定”逻辑
逆向揭示了 Claude Code 使用三种互不兼容的布尔判定方式,这为用户配置带来了隐蔽的坑:
| 判定方式 | 代表开关 | “开启”条件 | 空字符串 "" 的效果 |
|---|---|---|---|
| 非空即生效 | DISABLE_TELEMETRY | 任何非空值 | ✅ 生效 |
isEnvTruthy() | CLAUDE_CODE_ENABLE_TELEMETRY | 仅 1/true/yes/on | ❌ 不生效 |
isEnvDefinedFalsy() | CLAUDE_CODE_ATTRIBUTION_HEADER | 仅 0/false/no/off 关闭 | ❌ 不算关闭 |
6.2 实际陷阱场景
# 用户以为关闭了遥测,但实际没生效:export CLAUDE_CODE_ENABLE_TELEMETRY="" # ❌ 空字符串不算"关闭"export CLAUDE_CODE_ENABLE_TELEMETRY=0 # ❌ "0"不算 truthy,但这里本来就是 opt-in# 用户以为关闭了归因头,但实际没生效:export CLAUDE_CODE_ATTRIBUTION_HEADER="" # ❌ 空字符串不满足 isEnvDefinedFalsy# 正确的关闭方式:export DISABLE_TELEMETRY=1 # ✅ 非空即生效,关闭 1P/Datadog/GrowthBookexport CLAUDE_CODE_ATTRIBUTION_HEADER=0 # ✅ isEnvDefinedFalsy 匹配
[!WARNING]
环境变量的判定逻辑不一致,可能导致用户误认为已经关闭了某项功能。在配置隐私相关开关时,建议使用明确的1/0值,避免空字符串。
7. --bare / CLAUDE_CODE_SIMPLE 的真相
CLI 帮助文本声称 --bare 模式会跳过 attribution,但代码分析显示这与实际实现不符:
| 声称行为 | 实际代码行为 |
|---|---|
| Skip attribution | services/api/claude.ts 仍然调用 getAttributionHeader(fingerprint) |
| — | constants/system.ts 的 isAttributionHeaderEnabled() 没有 isBareMode() 条件判断 |
[!IMPORTANT]
--bare模式在主 API 请求的归因块上并未生效。如果用户依赖--bare来减少数据上传,这是一个需要注意的差距。
8. BigQuery Metrics 的特殊生命周期
BigQuery metrics 管线展现了一个有趣的缓存驱动生命周期问题:
sequenceDiagram participant Client as Claude Code Client participant Cache as 磁盘缓存 participant Server as Anthropic Server participant BQ as BigQuery Client->>Cache: 检查 metrics_enabled 缓存 alt 缓存命中且未过期 Cache-->>Client: enabled: true (即使你刚设了 DISABLE) Client->>BQ: 继续上报 ⚠️ else 缓存未命中或已过期 Client->>Server: GET /api/claude_code/organizations/metrics_enabled Server-->>Client: enabled: false Client->>Cache: 写入 enabled: false Client->>BQ: 停止上报 ✅ end
[!NOTE]
即使设置了CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,如果磁盘缓存中仍有未过期的enabled: true,BigQuery 上报可能不会立刻停止。这是一种最终一致性行为,不是即时关闭。
9. 服务端视角的关联矩阵
如果站在 Anthropic 服务端的角度,将收到的所有字段按关联维度组织:
graph LR subgraph WHO["谁在用?"] W1["Authorization"] W2["x-api-key"] W3["account_uuid"] W4["organization_uuid"] W5["email"] end subgraph WHAT_DEVICE["哪台设备?"] D1["device_id"] D2["user.id"] D3["GrowthBook id"] end subgraph WHAT_SESSION["哪次会话?"] S1["session_id"] S2["X-Claude-Code-Session-Id"] end subgraph IS_LEGIT["是否合法客户端?"] L1["cch attestation"] L2["x-anthropic-billing-header"] L3["User-Agent"] L4["x-app / x-client-app"] end subgraph WHERE["运行环境?"] E1["apiBaseUrlHost"] E2["remote-container-id"] E3["platform / arch"] E4["rh (repo hash)"] end WHO ---|关联| WHAT_DEVICE WHAT_DEVICE ---|关联| WHAT_SESSION IS_LEGIT ---|辅助| WHO WHERE ---|辅助| WHAT_DEVICE style WHO fill:#e94560,stroke:#e94560,color:#fff style WHAT_DEVICE fill:#0f3460,stroke:#0f3460,color:#fff style WHAT_SESSION fill:#16213e,stroke:#16213e,color:#fff style IS_LEGIT fill:#f39c12,stroke:#f39c12,color:#fff style WHERE fill:#2ecc71,stroke:#2ecc71,color:#fff
10. 关键发现总结
10.1 架构层面
| # | 发现 | 影响 |
|---|---|---|
| 1 | 三层正交身份锚定(账号/设备/会话) | 单维度规避无效 |
| 2 | 五条独立遥测管线,无统一总开关 | 隐私配置复杂度高 |
| 3 | 同源字段在多管线间冗余复用 | 关闭部分管线仍可关联 |
| 4 | 环境变量使用三种不同的真值判定逻辑 | 配置容易出错 |
| 5 | cch attestation 架构已就位(当前占位) | 未来可启用远程证明 |
10.2 隐私层面
| # | 发现 | 影响 |
|---|---|---|
| 1 | 身份关联度最强的字段无法关闭 | 彻底匿名不可能 |
| 2 | --bare 模式的归因跳过未实际生效 | 用户预期与实际不符 |
| 3 | BigQuery metrics 有缓存延迟 | 关闭不是即时的 |
| 4 | Beta tracing 管线独立于普通遥测开关 | 存在感知盲区 |
| 5 | messages 正文可能包含用户名/路径/仓库信息 | 非结构化信息泄露风险 |
10.3 风控层面
| # | 发现 | 影响 |
|---|---|---|
| 1 | 客户端证明 (cch) + 归因头组成第一防线 | 伪造客户端难度将提升 |
| 2 | session_id 四路同步上报 | 行为序列可完整重建 |
| 3 | 环境指纹组合 (platform + arch + terminal + node) | 被动指纹识别能力 |
| 4 | rh (repo hash) 可做仓库级聚合 | 项目级行为分析 |
11. 推荐的最小化隐私配置
基于逆向分析,如果目标是在不影响核心功能的前提下最大程度减少数据上传:
# 1. 关闭内部分析链路(1P / Datadog / GrowthBook)export DISABLE_TELEMETRY=1# 2. 关闭非必要网络流量(更强的一层)export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1# 3. 关闭归因头(包括 cch)export CLAUDE_CODE_ATTRIBUTION_HEADER=0# 4. 确保 Standard OTel 不被启用# (默认关闭,但如果之前开启过需要显式关)unset CLAUDE_CODE_ENABLE_TELEMETRY# 5. 确保 Beta Tracing 不被启用unset ENABLE_BETA_TRACING_DETAILEDunset BETA_TRACING_ENDPOINT# 6. 如果开启了 OTel,确保不上传正文export OTEL_LOG_USER_PROMPTS=0export OTEL_LOG_TOOL_DETAILS=0export OTEL_LOG_TOOL_CONTENT=0
[!CAUTION]
即使应用了以上所有配置,以下数据仍会上传:
- 完整的
messages请求体(核心功能需要)Authorization/x-api-key(认证需要)X-Claude-Code-Session-Id(硬编码注入)User-Agent/x-app(硬编码注入)device_id/user.id(在任何已启用的遥测路径中常驻)
12. 值得持续关注的演进信号
cchattestation 从占位值变为真实令牌:一旦启用,将标志着 Anthropic 开始对客户端真伪进行硬校验NATIVE_CLIENT_ATTESTATIONbuild flag 的变化:这是 attestation 机制生效的前提条件- 新增的 GrowthBook feature gate:Anthropic 通过 GrowthBook 进行服务端控制,新增 gate 可能意味着新的风控策略
- Beta tracing 管线的正式化:目前是 beta 状态,一旦正式化,可能意味着正文级遥测成为常规能力
x-anthropic-billing-header中新增字段:这个文本块是归因信息的主载体,新增字段可能代表新的风控维度
本分析基于 Claude Code v2.1.88 逆向还原源码,所有结论仅反映客户端实现。服务端行为和策略无法从客户端代码中确认。
Leave a comment