【翻译】Claude Code 正在对请求进行隐写标记
mayfly
mayfly
独眼情报
2026年7月1日 10:24
湖北
在小说阅读器读本章
去阅读
我出于隐私原因检查了 Claude Code,发现了基于 API 基础 URL 和时区的隐藏系统提示标记。
我出于隐私考虑检查了 Claude Code。
大多数开发者会给他们的代理工具链赋予过多的访问权限——文件系统、shell、git、浏览器访问,甚至现在的计算机使用权限。这正是重点所在。他们需要足够的上下文来完成有用的工作。
这也意味着客户端本身值得严格审查。如果一个编码代理可以读取你的代码库并运行命令,那么分发它的二进制文件就应该很“无聊”(例如 pi harness)。
于是我查看了我本地的 Claude Code(2.1.196)安装。
none !importantnone !importantnone !importantnone !important标记none !importantnone !importantnone !importantnone !important
在 Claude Code 的二进制文件中,存在一个函数会修改插入到系统提示中的当前日期字符串。
正常的字符串看起来是这样的:
Today's date is 2026-06-30.
Claude Code 可以静默修改两处内容:
- “Today's” 中的撇号
- 日期分隔符,从
-改为/
以下是相关代码(已从压缩后的 bundle 中清理):
function Zup() {
if (Crt()) null;
let host = Qup();
let timezone = e0t();
let cnTZ = timezone === \"Asia/Shanghai\" || timezone === \"Asia/Urumqi\";
if (!host) {
return {
known: false,
labKw: false,
cnTZ,
host: null,
};
}
return {
known: Jup().some((domain) => host === domain || host.endsWith(\".\" + domain)),
labKw: Xup().some((keyword) => host.includes(keyword)),
cnTZ,
host,
};
}
function edp(known, labKw) {
if (!known && !labKw) return \"'\";
if (known && !labKw) return \"\\u2019\";
if (!known && labKw) return \"\\u02BC\";
return \"\\u02B9\";
}
function Vla(date) {
let marker = Zup();
let apostrophe = edp(marker?.known ?? false, marker?.labKw ?? false);
let renderedDate = marker?.cnTZ ? date.replaceAll(\"-\", \"/\") : date;
return `Today${apostrophe}s date is ${renderedDate}.`;
}
这是提示词隐写术(prompt steganography)——一种将数据隐藏在明面上的技术。
可见的句子仍然像普通的日期描述,模型和用户看到的都是无聊的内容。但原始请求中已经嵌入了标记。
none !importantnone !importantnone !importantnone !important检查机制none !importantnone !importantnone !importantnone !important
function Crt() {
let baseUrl = process.env.ANTHROPIC_BASE_URL;
if (!baseUrl) return true;
return Rrt(baseUrl);
}
function Rrt(baseUrl) {
try {
let host = new URL(baseUrl).host;
return [\"api.anthropic.com\"].includes(host);
} catch {
return false;
}
}
function Qup() {
let baseUrl = process.env.ANTHROPIC_BASE_URL;
if (!baseUrl) return null;
try {
return new URL(baseUrl).hostname.toLowerCase();
} catch {
return null;
}
}
触发条件是 ANTHROPIC_BASE_URL(Claude Code 的 API 基础 URL 覆盖设置)。
随后它会检查以下几项:
- 系统时区是否为
Asia/Shanghai或Asia/Urumqi - API 基础 URL 的主机名是否匹配解码后的域名列表
- 主机名是否包含特定的 AI 实验室关键词
时区检查会把日期从:
2026-06-30
变成:
2026/06/30
主机名检查则会改变撇号字符:
| 条件 | 使用的撇号字符 |
|---|---|
| 正常情况 | ' |
| 已知域名 | \\u2019 |
| 包含实验室关键词 | \\u02BC |
| 同时满足已知域名和实验室关键词 | \\u02B9 |
这些都是视觉上极其细微的变化,在大多数等宽字体中几乎无法察觉。
none !importantnone !importantnone !importantnone !important混淆的列表none !importantnone !importantnone !importantnone !important
域名和关键词列表以 base64 字符串存储,并使用密钥 91 进行 XOR 解码。
var Kup = 91;
function Gla(encoded) {
let bytes = Buffer.from(encoded, \"base64\");
let out = \"\";
for (let byte of bytes) {
out += String.fromCharCode(byte ^ Kup);
}
return out.split(\",\");
}
解码后的实验室关键词列表为:
deepseek,moonshot,minimax,xaminim,zhipu,bigmodel,baichuan,stepfun,01ai,dashscope,volces
解码后的域名列表要大得多,包含中国企业域名、AI 公司域名,以及大量代理、经销商和网关域名。
完整示例:
const knownDomains = [
\"cn\",
\"sankuai.com\",
\"netease.com\",
\"163.com\",
\"baidu-int.com\",
\"baidu.com\",
\"alibaba-inc.com\",
\"alipay.com\",
\"antgroup-inc.cn\",
\"kuaishou.com\",
\"bytedance.net\",
\"xiaohongshu.com\",
\"ctripcorp.com\",
\"jd.com\",
\"jdcloud.com\",
\"bilibili.co\",
\"iflytek.com\",
\"stepfun-inc.com\",
\"aliyuncs.com\",
\"cn-shanghai.fcapp.run\",
\"cn-beijing.fcapp.run\",
\"xaminim.com\",
\"moonshot.ai\",
\"anyrouter.top\",
\"packyapi.com\",
\"aicodemirror.com\",
\"aigocode.com\",
\"hongshan.com\",
\"iwhalecloud.com\",
\"dhcoder.net\",
\"lemongpt.top\",
\"zhihuiapi.top\",
\"intsig.net\",
\"high-five-ai.xyz\",
\"cloudsway.net\",
\"4sapi.com\",
\"529961.com\",
\"88996.cloud\",
\"88code.ai\",
\"88code.org\",
\"91code.pro\",
\"992236.xyz\",
\"ai.codeqaq.com\",
\"ai.hybgzs.com\",
\"ai.kjvhh.com\",
\"aicanapi.com\",
\"aicoding.sh\",
\"aifast.site\",
\"aihubmix.com\",
\"anmory.com\",
\"api.5202030.xyz\",
\"api.ablai.top\",
\"api.bianxie.ai\",
\"api.bltcy.ai\",
\"api.cpass.cc\",
\"api.dev88.tech\",
\"api.dreamger.com\",
\"api.expansion.chat\",
\"api.gueai.com\",
\"api.holdai.top\",
\"api.ikuncode.cc\",
\"api.lconai.com\",
\"api.linkapi.org\",
\"api.mkeai.com\",
\"api.nekoapi.com\",
\"api.oaipro.com\",
\"api.ruyun.fun\",
\"api.ssopen.top\",
\"api.tu-zi.com\",
\"api.uglycat.cc\",
\"api.v3.cm\",
\"api.whatai.cc\",
\"api.wpgzs.top\",
\"api.xty.app\",
\"api.yuegle.com\",
\"api.zzyu.me\",
\"apimart.ai\",
\"apipro.maynor1024.live\",
\"apiyi.com\",
\"applyj.hiapi.top\",
\"augmunt.com\",
\"b4u.qzz.io\",
\"clauddy.com\",
\"claude-code-hub.app\",
\"claude-opus.top\",
\"claudeide.net\",
\"co.yes.vg\",
\"code.wenwen-ai.com\",
\"code.x-aio.com\",
\"codeilab.com\",
\"cubence.com\",
\"deeprouter.top\",
\"dimaray.com\",
\"dmxapi.com\",
\"docs.aigc2d.com\",
\"duckcoding.com\",
\"fk.hshwk.org\",
\"flapcode.com\",
\"foxcode.hshwk.org\",
\"foxcode.rjj.cc\",
\"fuli.hxi.me\",
\"getgoapi.com\",
\"gpt.zhizengzeng.com\",
\"gptgod.cloud\",
\"gptkey.eu.org\",
\"gptpay.store\",
\"hdgsb.com\",
\"henapi.top\",
\"instcopilot-api.com\",
\"jeniya.top\",
\"jiekou.ai\",
\"kg-api.cloud\",
\"n1n.ai\",
\"new-api.u4vr.com\",
\"new.xychatai.com\",
\"one-api.bltcy.top\",
\"one.ocoolai.com\",
\"oneapi.paintbot.top\",
\"open.xiaojingai.com\",
\"openclaude.me\",
\"opus.gptuu.com\",
\"poloai.top\",
\"poloapi.top\",
\"privnode.com\",
\"proxyai.com\",
\"qinzhiai.com\",
\"right.codes\",
\"runanytime.hxi.me\",
\"sssaicode.com\",
\"store.zzyus.top\",
\"tiantianai.pro\",
\"uiuiapi.com\",
\"uniapi.ai\",
\"vip.undyingapi.com\",
\"wolfai.top\",
\"wzw.de5.net\",
\"wzw.pp.ua\",
\"xairouter.com\",
\"xaixapi.com\",
\"xiaohuapi.site\",
\"xiaohumini.site\",
\"xy.poloapi.com\",
\"yansd666.com\",
\"yansd666.top\",
\"yunwu.ai\",
\"yunwu.zeabur.app\",
\"zenmux.ai\",
];
const labKeywords = [
\"deepseek\",
\"moonshot\",
\"minimax\",
\"xaminim\",
\"zhipu\",
\"bigmodel\",
\"baichuan\",
\"stepfun\",
\"01ai\",
\"dashscope\",
\"volces\",
];
none !importantnone !importantnone !importantnone !important标记如何传递none !importantnone !importantnone !importantnone !important
日期函数在构建代理上下文时被调用:
{
...userEmail && {
userEmail: `The user's email address is ${userEmail}.`
},
...attachedProject && {
attachedProject
},
currentDate: Vla(GSe())
}
因此这个标记会成为发送给模型的系统上下文的一部分(Anthropic 很可能在后端进行解析)。
none !importantnone !importantnone !importantnone !important我的本地安装情况none !importantnone !importantnone !importantnone !important
我安装的二进制文件由 Anthropic 签名:
Identifier=com.anthropic.claude-code
TeamIdentifier=Q6L2SF6YDW
Timestamp=Jun 29, 2026
SHA256=6fc6e61ab7582c2bf241225ff90d9f79e91d69380cb9589fc9dedd3a30070f5a
我当前 shell 中 ANTHROPIC_BASE_URL 未设置,时区为:
Asia/Hong_Kong
因此在我的机器上、当前环境下,这个路径会生成正常的撇号和标准的 YYYY-MM-DD 日期字符串。
none !importantnone !importantnone !importantnone !important令人担忧的点none !importantnone !importantnone !importantnone !important
Anthropic 可能希望检测 API 经销商、未经授权的 Claude Code 网关,以及模型“蒸馏攻击”管道。自定义 ANTHROPIC_BASE_URL 指向已知经销商域名是一个有用的信号;主机名包含 deepseek 或 zhipu 也是有用信号。
这部分逻辑说得通,但实现方式很奇怪。
CC 会使用近乎不可见的 Unicode 标记静默修改系统提示。它把代理/网关分类信息编码进看起来像普通英语的句子中,并将域名列表隐藏在 XOR 和 base64 之后。这不是恶意功能,但对于一个需要开发者信任的开发工具来说,这样的设计选择相当奇怪。
编码代理已经生活在一条可怕的边界上。它们可以检查代码、意外总结秘密、运行命令、安装包、编辑文件,并在你的本地机器上推送提交。大多数开发者接受这一点,是因为生产力提升值得冒这个风险。
真正开发者的信任,取决于那些“无聊”的行为。
如果客户端想要检测自定义 API 网关,它可以直白地说出来——发送一个有文档说明的显式遥测字段、公开政策、写入发布说明。
把信号藏在系统提示里,会让其他所有隐私声明都更难令人相信。
none !importantnone !importantnone !importantnone !important实际影响none !importantnone !importantnone !importantnone !important
对大多数用户来说,这个路径大概率保持不活跃。
如果你使用官方 Anthropic API 端点,Crt() 会提前返回;如果 ANTHROPIC_BASE_URL 未设置,Crt() 也会提前返回;正常使用场景下,日期提示会保持“无聊”状态。
有趣的情况是人们通过自定义基础 URL 来路由 Claude Code,包括:
- 内部网关
- 本地代理
- 模型路由器
- 经销商
- 研究环境
在这些情况下,Claude Code 会对主机名进行分类,并把结果编码进提示中。
绕过方法也非常简单:修改主机名、修改时区、修补二进制文件、包装进程。任何认真的对手都能让这个信号失效。
因此,这个功能主要惩罚了那些更容易被指纹识别的人:那些做着奇怪但合法事情的普通开发者。
none !importantnone !importantnone !importantnone !important一些想法none !importantnone !importantnone !importantnone !important
我认为这本可以更明确一些。
开发者工具可以强制执行条款,API 提供商可以检测滥用行为,公司也可以保护自己的模型。
当一个拥有文件系统和 shell 访问权限的工具,开始把分类比特隐藏在不可见的提示标点符号里时,正确的反应就是严格审查。
信任,是在那些无聊的细节中赢得的。
原文链接:https://thereallo.dev/blog/claude-code-prompt-steganography
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论