基于 @anthropic-ai/claude-code@2.1.88 逆向还原源码的全面审视 摘要 本文基于对 Claude Code v2.1.88 客户端逆向还原代码的系统性梳理,从身份追踪体系、风控机制设计、遥测管线架构与隐私控制面四个维度进行深度分析。核心发现是:Claude Code 构建了一套多层级、多链路、高冗余的用户/设备/会话关联体系,其设计远超简单的”产品分析”需求,呈现出工业级风控基础设施的特征。 1. 架构概览:三层身份锚定模型 核心洞察 Claude Code 的身份追踪不是”一个 ID 打天下”,而是构建了三层正交锚定: 层级 稳定性 粒度 可关闭性 账号层 跨设备稳定 最粗(同一人的所有设备) ❌ 认证不可关闭 设备层 跨重启稳定 中(单台设备) ❌ 无字段级开关 会话层 单次运行内稳定 最细(一次交互流程) ❌ 无字段级开关 这种设计的含义是:即使用户切换了账号,设备层 ID 仍然可以将不同账号关联到同一物理设备;即使用户更换了设备,账号层 ID 仍然可以将不同设备关联到同一用户。 2. 同源关系深度解剖 2.1 最关键的同源链条 逆向代码揭示的一个核心架构特征是字段同源复用——表面上看起来独立的十几个字段,实际上只有少数几个”源头”。 2.2 这意味着什么 [!IMPORTANT]同源复用意味着服务端可以通过任何一条上报链路获得完整的用户画像关联。即使某些遥测链路被关闭,主请求中携带的认证信息和会话头已经足以完成身份锚定。 从工程视角看,这种冗余有两种可能解释: 实际情况很可能是两者兼具。 3. 风控机制的四层防线…

Written by

×

Claude Code 深度架构分析

基于 @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]
同源复用意味着服务端可以通过任何一条上报链路获得完整的用户画像关联。即使某些遥测链路被关闭,主请求中携带的认证信息和会话头已经足以完成身份锚定。

从工程视角看,这种冗余有两种可能解释:

  1. 防御性工程:不同团队(API、Analytics、Infra)各自需要独立可靠的用户关联键,同源是自然结果
  2. 刻意冗余:确保即使在部分链路失败或被关闭的情况下,仍有足够的信号完成用户关联

实际情况很可能是两者兼具。


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]
cch attestation 虽然目前使用占位值,但其架构已经搭好。一旦 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 管线对比

属性主 API1P 事件GrowthBookStandard OTelBeta Tracing
核心开关无法关闭DISABLE_TELEMETRYDISABLE_TELEMETRYCLAUDE_CODE_ENABLE_TELEMETRYENABLE_BETA_TRACING_DETAILED
默认状态始终开启开启开启关闭关闭
携带正文✅ 完整 messages❌ metadata 级❌ attribute 级可选(默认关)✅ system prompt / tool I/O
携带身份✅ 认证 + 会话✅ device + session + account✅ device + session + account✅ user.id + session.id取决于配置
服务端控制GrowthBook killswitchGrowthBook 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_TELEMETRY1/true/yes/on❌ 不生效
isEnvDefinedFalsy()CLAUDE_CODE_ATTRIBUTION_HEADER0/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/GrowthBook
export CLAUDE_CODE_ATTRIBUTION_HEADER=0 # ✅ isEnvDefinedFalsy 匹配

[!WARNING]
环境变量的判定逻辑不一致,可能导致用户误认为已经关闭了某项功能。在配置隐私相关开关时,建议使用明确的 1/0 值,避免空字符串。


7. --bare / CLAUDE_CODE_SIMPLE 的真相

CLI 帮助文本声称 --bare 模式会跳过 attribution,但代码分析显示这与实际实现不符

声称行为实际代码行为
Skip attributionservices/api/claude.ts 仍然调用 getAttributionHeader(fingerprint)
constants/system.tsisAttributionHeaderEnabled() 没有 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环境变量使用三种不同的真值判定逻辑配置容易出错
5cch attestation 架构已就位(当前占位)未来可启用远程证明

10.2 隐私层面

#发现影响
1身份关联度最强的字段无法关闭彻底匿名不可能
2--bare 模式的归因跳过未实际生效用户预期与实际不符
3BigQuery metrics 有缓存延迟关闭不是即时的
4Beta tracing 管线独立于普通遥测开关存在感知盲区
5messages 正文可能包含用户名/路径/仓库信息非结构化信息泄露风险

10.3 风控层面

#发现影响
1客户端证明 (cch) + 归因头组成第一防线伪造客户端难度将提升
2session_id 四路同步上报行为序列可完整重建
3环境指纹组合 (platform + arch + terminal + node)被动指纹识别能力
4rh (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_DETAILED
unset BETA_TRACING_ENDPOINT
# 6. 如果开启了 OTel,确保不上传正文
export OTEL_LOG_USER_PROMPTS=0
export OTEL_LOG_TOOL_DETAILS=0
export 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. 值得持续关注的演进信号

  1. cch attestation 从占位值变为真实令牌:一旦启用,将标志着 Anthropic 开始对客户端真伪进行硬校验
  2. NATIVE_CLIENT_ATTESTATION build flag 的变化:这是 attestation 机制生效的前提条件
  3. 新增的 GrowthBook feature gate:Anthropic 通过 GrowthBook 进行服务端控制,新增 gate 可能意味着新的风控策略
  4. Beta tracing 管线的正式化:目前是 beta 状态,一旦正式化,可能意味着正文级遥测成为常规能力
  5. x-anthropic-billing-header 中新增字段:这个文本块是归因信息的主载体,新增字段可能代表新的风控维度

本分析基于 Claude Code v2.1.88 逆向还原源码,所有结论仅反映客户端实现。服务端行为和策略无法从客户端代码中确认。

Leave a comment