ClaudeCode(2.1.283)逆向和完整遥测分析"

admin 2026-10-16 04:22:52 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

ClaudeCode(2.1.283)逆向和完整遥测分析

原创

为了安全鸭
为了安全鸭

冲鸭安全

2026年10月5日 22:00
北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

前言

最近在开中转站,众所周知sub2api的特征是非常多的,所以我完整的逆向了cladue code的全部协议一比一对特征解决特征,但是越来越发现这玩意非常的离谱,有些已经超出代码编辑工具的边界了,故在此公开分析报告,我用的是我电脑上的Claude code 的2.1.283的版本。

Claude code的遥测

Claudecode存在一个遥测系统,而这个Claude code的遥测系统不会随着你用中转站而关闭。也就是说你用了他们的产品就会发送遥测数据给Claude code,除非你使用

CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1

这个环境变量把他关闭。

function gmt() {
    if (process.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC)
        return \"essential-traffic\";

    if (process.env.DISABLE_TELEMETRY)
        return \"no-telemetry\";

    if (Ne(process.env.DO_NOT_TRACK))
        return \"no-telemetry\";

    return \"default\";
}

function It() {
    return gmt() === \"essential-traffic\";
}

function $D() {
    return gmt() !== \"default\";
}

一旦遥测打开,后续的信息都会发送给:

https://api.anthropic.com/api/event_logging/v2/batch

让我们看看他有什么行为

Claude code唯一标识符

当你装Claude code的时候,cc会在你电脑上生成一个随机的标识符

// 生成随机编号。
let s = Ed(32).toString(\"hex\");

// 写入本地配置,字段名叫 userID。
Ee(g => ({
    ...g,
    userID: s
}), e);

跟外挂机器码修改一样,如果你不处理它,你就会被永久标记

模型信息

如果你用第三方API,比如zhipu的或者deepseek,Claude code依然会上传上去模型使用信息,会话ID,用户类型
模型使用信息的逻辑是:

// 取得当前模型名称。
let n = e.model ? String(e.model) : it();

// 经过客户端转换。
D = Jdn(n);

// 放入元数据。
model: D,

他会把模型名字去
https://downloads.claude.ai/model-catalog/v1/catalog.json

 ```javascript
bne = [
    \"claude-3-5-haiku\",
    \"claude-3-5-sonnet\",
    \"claude-3-7-sonnet\",
    \"claude-fable-5\",
    \"claude-fable-5-1\",
    \"claude-haiku-4-5\",
    \"claude-mythos-5\",
    \"claude-mythos-5-1\",
    \"claude-opus-4-0\",
    \"claude-opus-4-1\",
    \"claude-opus-4-5\",
    \"claude-opus-4-6\",
    \"claude-opus-4-7\",
    \"claude-opus-4-8\",
    \"claude-opus-5\",
    \"claude-opus-5-5\",
    \"claude-sonnet-4-0\",
    \"claude-sonnet-4-5\",
    \"claude-sonnet-4-6\",
    \"claude-sonnet-5\"
];

j1 = [
    \"sonnet\",
    \"opus\",
    \"haiku\",
    \"fable\",
    \"best\",
    \"sonnet[1m]\",
    \"opus[1m]\",
    \"fable[1m]\",
    \"opusplan\"
];

var Fpt = \"claude-mythos-preview\";

拉一个列表下来,如果模型不在这里面,会标记为”confidential”如果在这里,会原样上传模型名字

token使用情况

即便是不用Claude订阅,走第三方API,也一样会上传你的token使用情况
包括不限于

压缩时候的情况

你的当前中转站URL(ANTHROPIC\_BASE\_URL)

function nMe() {
    return {
        ...process.env.ANTHROPIC_BASE_URL && {
            baseUrl: XMo(process.env.ANTHROPIC_BASE_URL)
        },

        ...process.env.ANTHROPIC_MODEL && {
            envModel: xt(process.env.ANTHROPIC_MODEL)
        },

        ...process.env.ANTHROPIC_SMALL_FAST_MODEL && {
            envSmallFastModel:
                xt(process.env.ANTHROPIC_SMALL_FAST_MODEL)
        }
    };
}

同一个客户端/会话用了多少 token、请求速度、是否重试、用了哪些运行模式、输入是否含图片/文档、system 和工具定义多大,以及一些可关联的哈希和请求编号。
这块非常多,看图吧:

其中有意思的是 default\_model

我们上面说了model会脱敏,而default\_model的”脱敏”是一种伪脱敏,具体来说,他会过一层正则

var Bw = /^[A-Za-z0-9._:[\\]-]{1,100}$/;

var Kw =
    /^[A-Za-z0-9._:[\\]-]{1,91}@\\d{8}(\\[\\d{1,3}[mM]\\])?$/;

function xt(e) {
    if (e == null)
        return;

    return Bw.test(e) || Kw.test(e)
        ? bn(e)
        : y(\"nonconforming\");
}

如果是这种格式

claude-sonnet-4-5
gpt-4.1
deepseek-chat
qwen3-32b
my_model:v1
sonnet[1m]

则会变成”confidential”
而如果是这种

provider/model      含 /
my model            含空格
模型一               含中文
model?version=1     含 ? 和 =

则会被标记
我能想到的场景是,我自己测评的模型,比如自己训练的CTF的模型,会被hit,如果用vllm,一般默认的后缀就是目录/模型名字比如这样:

从而变成”nonconforming”

skills和插件

当你用到skill的时候(请求中用了skill),无论是不是claude订阅还是第三方,都会上传skill名字

function _W({
    rawName: e,
    canonicalName: n,
    isMcp: r,
    isBuiltIn: s,
    isBundled: g,
    isOfficial: h
}) {
    let S = r
        ? \"mcp\"
        : s || g || h
            ? e
            : \"custom\";

    return {
        sanitizedName: bn(S),
        skillNameHash:
            S === \"custom\" ? lhr(n) : {}
    };
}

你的插件也是,也会上传对应的名字

function bW(e, n, r = null) {
    let s = Kge(e, n) ?? n;

    return {
        _PROTO_plugin_name: e,

        ...s && {
            _PROTO_marketplace_name: s
        },

        ...zcn(e, n, r)
    };
}

MCP与工具使用

claude code会上传你的工具使用情况,包含工具名字

而如果是MCP服务器,自定义的,则会脱敏走hash上传

var fP = \"claude-plugin-telemetry-v1\";

function aye(e) {
    return cP(\"sha256\")
        .update(e + fP)
        .digest(\"hex\")
        .slice(0, 16);
}

有意思的是还会上传你是拒绝还是同意,你为此等了多久(wtf)

i(\"tengu_tool_use_rejected_in_prompt\", {
    ...kP(e, n, s, h),
    ...g,
    ...S,

    ...r.type === \"hook\"
        ? { isHook: !0 }
        : {
            hasFeedback:
                r.type === \"user_reject\"
                    ? r.hasFeedback
                    : !1
        }
});

运行环境

这些是挺标准的:

然而在以下条件下,Claudecode会额外上传tag

github的action

isGithubAction:
    Ne(process.env.GITHUB_ACTIONS),

isClaudeCodeAction:
    Ne(process.env.CLAUDE_CODE_ACTION)

如果是action环境,上传

事件类型、runner 环境/系统、action ref

WSL

通过字符串比对是否是微软的WSL:

getWslVersion() {
    if (this.wslVersion !== null)
        return this.wslVersion;

    if (this.sources.platform !== \"linux\") {
        this.wslVersion = void 0;
        return;
    }

    let e = this.kernelString();

    if (e === void 0) {
        this.wslVersion = void 0;
        return;
    }

    let r = e.match(/wsl(\\d+)/);

    if (r && r[1])
        this.wslVersion = r[1];
    else if (e.includes(\"microsoft\"))
        this.wslVersion = \"1\";
    else
        this.wslVersion = void 0;

    return this.wslVersion;
}

如果是微软的WSL,则会上传WSL 版本、Linux 发行版及版本、内核信息

docker

如果你在docker下用它,他会通过

if (process.env.KUBERNETES_SERVICE_HOST)
    return \"kubernetes\";

if (o.isDockerenvPresent())
    return \"docker\";

if (p.platform === \"darwin\")
    return \"unknown-darwin\";

if (p.platform === \"linux\")
    return \"unknown-linux\";

if (p.platform === \"win32\")
    return \"unknown-win32\";

return \"unknown\";

识别你是不是docker

进程信息

会上传当前进程的信息

git信息

Claude code会上传你的git url的前20字节并且做hash

async function ZWr() {
    let e = await Vne();

    if (!e)
        return null;

    let n = w2(e);

    if (!n)
        return null;

    return So(\"sha256\")
        .update(n)
        .digest(\"hex\")
        .substring(0, 16);
}

并且知道你的当前 HEAD 的提交 SHA
猜测是检查,哪些账户在开发相同的项目(类似于组织指纹)

如果你把Claude code放到github action,他会直接上传github的信息:

if (n.githubActionsMetadata) {
    let se = n.githubActionsMetadata;

    ee.github_actions_metadata = {
        actor_id: se.actorId,
        repository_id: se.repositoryId,
        repository_owner_id: se.repositoryOwnerId
    };
}
  • 操作者 ID;
  • 仓库 ID;
  • 仓库所属用户/组织 ID。

GrowthBook云控

在启动的时候,Claude code会发送

到

普通评估:
POST https://api.anthropic.com/api/eval/sdk-zAZezfDKGoZuXXKe

带认证评估分支:
POST https://api.anthropic.com/api/eval-authed/sdk-zAZezfDKGoZuXXKe

随后看服务端返回了什么云控功能开关:

{
  \"features\": {
    \"某个实验功能\": {
      \"value\": true,
      \"source\": \"experiment\",
      \"experiment\": {
        \"key\": \"实验编号\"
      },
      \"experimentResult\": {
        \"variationId\": 1
      }
    }
  }
}

这个是典型的云控行为,有意思的是这个云控数量达到了惊人的648个,而且很多意义不明,这里挑出来一些AI跑过的

tengu\_heron\_brook 远程服务端提示词注入

这个神奇的flag接受远程服务端的提示词并且注入到系统上下文中
客户端会读一个client\_data

GET <base>/api/claude_cli/bootstrap
    → 响应中的 client_data
    → 本地 clientDataCacheSlots
    → cd()

然后判断这个key

function hXn() {
    let e = nSt();

    if (!e)
        return null;

    return i(\"tengu_heron_brook_applied\", {
        len: e.value.length,
        fromClientData: e.fromClientData
    }), e.value;
}

然后塞到system提示词里面。
这意味着如果官方给你换了一个能执行任意代码的模型 结合这个 就能实现任意代码执行。
当然我们不能那么坏的去看A÷是吧

tengu\_official\_plugin\_prompt\_overrides 覆盖插件提示词

官方可以下云控,去控制自己的MCP和工具的提示词,这里要说明的是,不是任意的,是官方自己的

{
    server_instructions: string,
    server_instructions_by_server: { [serverName]: string },
    tools: { [toolName]: string },
    search_hints: { [toolName]: string },
    param_descriptions: {
        [toolName]: { [parameterName]: string }
    },
    prompts: { [promptName]: string },
    skills: { [skillName]: string }
}
字段 实际用途
server\_instructions 覆盖 MCP 连接 server instructions
server\_instructions\_by\_server 按 server 名覆盖 instructions
tools 覆盖已有 MCP 工具 description
search\_hints 覆盖已有工具搜索提示
param\_descriptions 改写已有 input schema properties 的 description
prompts 覆盖 MCP prompt 的 description
skills 覆盖发现的 MCP skill 的 description

tengu\_max\_version\_config 更新时候的最低版本

云控设置一个最低版本,更新的版本不能超过这里配置的版本

async function Qwe() {
    let e = await Pe();
    let n = e.external || void 0;
    let o = n ? R.parse(n)?.version ?? void 0 : void 0;
    // 原函数还有非法版本告警;此处省略。
    return {
        maxVersion: o,
        forceDowngradeEnabled:
            e.external_force_downgrade === !0
    };
}
async function Pe() {
    try { return await k1(\"tengu_max_version_config\", {}); }
    catch (e) { return d(e), {}; }
}

sub2api等各种中转站检测

众所周知 x-anthropic-billing-header是带了cc\_version这个字段的。

cc\_version这个字段官方 Claude Code 取第一条 user 文本的第:

4、7、20

三个位置,然后计算:

SHA256(
 \"59cf53e54c78\"
 + text[4]
 + text[7]
 + text[20]
 + \"2.1.283\"
) 的前 3 位十六进制

官方是 JavaScript,所以字符串下标按 UTF-16 字符单元。

而sub2api项目的当前 Go 代码:

chars = append(chars, firstText[i])

按的是 UTF-8 字节

所以会导致sub2api的项目,真实 Claude Code 先生成:

cc_version=2.1.283.<官方后缀>;

请求到 SUB2API 后,当前项目的:

https://github.com/Wei-Shaw/sub2api/blob/a60a29549f488a854966aaec9541abbe006cac22/backend/internal/service/gateway\_billing\_block.go#L32

syncBillingHeaderVersion()

会重新计算后缀,但项目按 UTF-8 字节取第 4、7、20 位,而官方按 JavaScript UTF-16 下标取值。

于是可能变成:

客户端:
cc_version=2.1.283.d80;

SUB2API 出站:
cc_version=2.1.283.fdc;

导致sub2api被检测

结论

最后附上gpt-6.1-sol的结论

Claude Code 是能力强、但不适合当作“透明、纯本地工具”信任的客户端。基于这次对 2.1.283 的静态分析,我的评价是:
工程能力强:工具、权限、子代理、压缩和远程任务机制完整,确实有不少安全检查。
隐私边界不直观:推理正文、产品遥测、辅助模型请求、反馈和文件交付是不同通道。用第三方 API 不代表其他通道自动关闭。
云端控制权较大:能调整功能参数,甚至追加模型指令、改变部分安全检查和更新签名强制策略。这扩大了你必须信任官方服务的范围。
适合普通开发;处理高度敏感代码时,应按“联网代理执行环境”管理,而不是只换个 baseurl 就放心。明确限制文件和网络权限、禁用不需要的遥测/远程功能、避免把凭据放进可读工作区,比单纯相信工具的“只读”标签更可靠。


ClaudeCode(2.1.283)逆向和完整遥测分析" 网络安全文章

ClaudeCode(2.1.283)逆向和完整遥测分析"

本文逆向分析了ClaudeCode2.1.283版本的遥测系统,揭示其即使使用第三方API中转站仍会上传用户数据至Anthropic,包括唯一标识符、模型信息、token使用情况、中转站URL、skills插件名称、工具使用情况、运行环境及git信息等。建议用户通过设置CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1环境变量关闭非必要遥测,以保护隐私安全。
过节宅家打游戏:《波斯王子:失落王冠》" 网络安全文章

过节宅家打游戏:《波斯王子:失落王冠》"

本文推荐单机游戏《波斯王子:失落王冠》,一款2.5D横版动作过关加寻宝游戏,节奏较慢,适合亲子探索。游戏地图广阔,场景丰富,包含天空之城、下水道、墓地、森林等。剧情围绕救王子展开,实际讲述国家三代人谋权篡位的故事。游戏包含时间回退等招牌技能,战斗华丽,武器多样。Steam售价约10元,性价比高。
(9.3分)CVE-2026-61500:HFS文件服务器认证绕过RCE" 网络安全文章

(9.3分)CVE-2026-61500:HFS文件服务器认证绕过RCE"

CVE-2026-61500是RejettoHFS3.0.0至3.2.0版本中的严重漏洞,CVSS评分9.3。根因是使用Math.random()生成会话签名密钥,该伪随机数生成器可预测,攻击者通过收集泄露的随机数输出,利用Z3求解器还原内部状态并回推密钥,伪造管理员会话Cookie实现认证绕过和远程代码执行。建议立即升级至3.2.1版本,无法升级时限制网络访问。
评论:0   参与:  0