Skip to content

Instantly share code, notes, and snippets.

@jerrylususu
Created February 13, 2026 11:37
Show Gist options
  • Select an option

  • Save jerrylususu/56130219fe286f7e495987b820e9d7dc to your computer and use it in GitHub Desktop.

Select an option

Save jerrylususu/56130219fe286f7e495987b820e9d7dc to your computer and use it in GitHub Desktop.
claude-code-break-cache-explore

deepdive

1. 问题陈述

待验证传言:

  • Claude Code 对非 Claude 模型会“恶意改 prompt”导致 cache 命中率降低。
  • 具体猜测:若 model_name != claude,则在 system prompt 上做细微空白字符扰动(每次响应都变),从而触发重算。

本次目标:基于最新 npm 正式包做静态取证,判断该逻辑是否存在。

2. 样本与时间

  • 日期:2026-02-13
  • 包:@anthropic-ai/claude-code@2.1.41
  • 下载文件:anthropic-ai-claude-code-2.1.41.tgz
  • 主代码:unpack/package/cli.js

3. 方法

3.1 获取样本

npm view @anthropic-ai/claude-code version dist-tags --json
npm pack @anthropic-ai/claude-code@2.1.41
mkdir -p unpack && tar -xzf anthropic-ai-claude-code-2.1.41.tgz -C unpack

3.2 解决压缩代码可读性问题

cli.js 高压缩,prettier OOM。改用 esbuild 成功展开:

npx --yes esbuild@0.25.0 unpack/package/cli.js --format=esm --target=es2022 --outfile=unpack/package/cli.esbuild.js

结果:unpack/package/cli.esbuild.jswc -l 为 284551 行)。

3.3 重点检索面

  1. prompt/cache 相关函数:Pc1, S2z, h2z, _Jq, xR7, bR7
  2. model 条件分支是否影响 system prompt 文本
  3. whitespace/zero-width 字符注入或替换
  4. “prompt cache break”原因来源

4. 关键证据

4.1 Prompt cache break 判定是“变更检测”,不是“注入扰动”

unpack/package/cli.esbuild.js:114795 附近:

  • 比较 system hash / tools hash / model / fastMode
  • 任一变化会标记 pendingChanges
  • 后续在 bR7 打点 [PROMPT CACHE BREAK] ...

对应事件上报位于:unpack/package/cli.esbuild.js:114842

这解释了 cache miss 的常规来源,但未显示“按非 claude 模型主动篡改文本”。

4.2 Pc1 仅构造 cache_control

unpack/package/cli.esbuild.js:251103

Pc1({ scope, querySource }) 返回结构是:

  • type: "ephemeral"
  • 可选 ttl: "1h"
  • 可选 scope: "global"

不含任何 prompt 文本改写。

4.3 主请求路径 _Jq 的 system/messages 构建不含“非 claude 改写空白”

unpack/package/cli.esbuild.js:251220 起:

  • q = [gK6(...), FK6(...), ...systemParts] 组装 system 段
  • T = h2z(q, ...) 为 system 段添加 cache_control
  • messages: S2z(...) 为最近消息添加 cache_control

h2z/S2z 行为是“附加 cache_control 元数据”,不是字符串替换。见:

  • unpack/package/cli.esbuild.js:251442
  • unpack/package/cli.esbuild.js:251447

4.4 FK6/gK6 含身份前缀与 attribution header,不做按模型空白扰动

  • FK6: unpack/package/cli.esbuild.js:72077
  • gK6: unpack/package/cli.esbuild.js:72089

这两处输出固定说明文本/头信息,未发现“model 非 claude 时替换空格”逻辑。

4.5 关于 whitespace 的实际代码用途

检索到 whitespace 相关代码主要是:

  • 统计模型返回全空白内容:tengu_model_whitespace_response
  • 过滤“全空白 assistant 消息”

位置:

  • unpack/package/cli.esbuild.js:256173
  • unpack/package/cli.esbuild.js:256902

这属于响应清洗,不是 system prompt 扰动。

5. 结论

@anthropic-ai/claude-code@2.1.41 的静态代码中:

  1. 没有找到“如果模型名不是 claude 就每次修改 system prompt 空白字符”的实现。
  2. 已确认的 cache miss 触发原因是常规检测:模型、system prompt、tools、fast mode 变化。
  3. 因此,基于当前样本,无法证明该“恶意改 prompt”传言为真。

6. 边界与后续可做

本次是静态取证,仍有两个边界:

  • 若外部“路由层/代理层”二次改写(例如第三方 router 包),该行为不在本包静态代码里。
  • 若运行期远端服务按请求头策略返回不同系统段,这需要动态抓包与对照实验验证。

建议下一步(如需更强证据):

  1. 用同一输入、同一模型、固定环境变量,比较连续两次请求 payload(本地 hook/代理抓取)
  2. 对比 @musistudio/claude-code-router 等路由器包,确认是否其实现导致 cache miss

note

2026-02-13 取证快照

  • 目标包确认:@anthropic-ai/claude-code@2.1.41(npm latest)
  • 下载并解包:anthropic-ai-claude-code-2.1.41.tgz
  • 关键障碍:cli.js 约 11.5MB 且高度压缩,prettier 在默认内存下 OOM
  • 解决方案:改用 esbuild 生成可读版本 unpack/package/cli.esbuild.js(约 28 万行)

初步结论

  • 暂未发现“若模型名非 claude 则每次改写 system prompt 空格”的逻辑。
  • 已定位到真实会导致 cache miss 的正常路径:
    • model 变化
    • system prompt 变化
    • tools schema 变化
    • fast mode 切换
  • 对应代码见 unpack/package/cli.esbuild.js:114795 及其后续告警上报段。

已核查关键点

  • Pc1 仅设置 cache_control(ephemeral / 1h / global scope),不改 prompt 文本:unpack/package/cli.esbuild.js:251103
  • 请求构建主流程 _Jq 中,systemmessagesh2z/S2z 构造;逻辑为加 cache_control 标记,不做字符串篡改:unpack/package/cli.esbuild.js:251231
  • FK6/gK6 仅是身份说明与 attribution header:unpack/package/cli.esbuild.js:72077, unpack/package/cli.esbuild.js:72089

有传言说 claude-code 对非 claude 模型会恶意改 prompt 降低命中率;你能证明这一点吗?

可能步骤

  1. 从npm拉取最新的 claude code 包
  2. 尝试从混淆后的代码中找相关逻辑;过程中随时更新 note.md;可以使用 py node 等工具,有需要可以从npm安装其他包到当前目录
  3. 深入记录问题、分析过程和结论到 deepdive.md

Claude Code的一些神秘更新导致Kimi K2.5的 Cache 命中率降低,目前 我们已经定位到问题并进行修复,各位可以继续快乐地在ClaudeCode里 使用 Kimi K2.5了

Adversarial cache recomputation: e.g., if model_name is not claude, edit the space symbol in system prompt for every response yo, i mean it's stupid and naive, but sounds like something Anthropic would

Token usage: total=805,542 input=797,475 (+ 2,147,968 cached) output=8,067 (reasoning 2,509)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment