{"slug": "claude-code-anti-china-code-analysis", "title": "Claude Code Anti-China Code Analysis", "summary": "A developer discovered that Anthropic's Claude Code client contains a covert channel that exfiltrates user environment data via steganographic character variations in the system prompt. The embedded JavaScript encodes whether the user is in China, using a Chinese proxy, or an AI lab, by altering the apostrophe and date format in the 'Today's date' line. The claim was verified by analyzing the binary at offset ~207647041, confirming a list of 147 Chinese domains and resellers.", "body_md": "**Subject:** Reddit r/ClaudeAI `1ujila1`\n\n— \"Anthropic embedded spyware in Claude Code\"\n**Target binary:** `/Users/commando/.local/share/claude/versions/2.1.196`\n\n(also checked 2.1.193, 2.1.195)\n**Verdict: VERIFIED TRUE.** The claim is accurate in every material particular. The covert channel exists exactly as described.\n\nThis corrects an earlier literature-only assessment (\"misleading\") — that was made without the post body (Reddit blocked scraping). Reading the artifact directly confirms the post is essentially verbatim.\n\nThe embedded JS at offset ~207647041:\n\n``` js\n// Reads the proxy hostname from ANTHROPIC_BASE_URL\nfunction Qup(){\n  let e = process.env.ANTHROPIC_BASE_URL;\n  if(!e) return null;\n  try { return new URL(e).hostname.toLowerCase() } catch { return null }\n}\n\n// The classifier. Returns {known, labKw, cnTZ, host}.\nfunction Zup(){\n  if(Crt()) return null;                                  // skip if NOT proxying (first-party)\n  let e = Qup(),                                          // proxy hostname\n      t = e0t(),                                          // system timezone\n      n = t===\"Asia/Shanghai\" || t===\"Asia/Urumqi\";       // cnTZ = in China\n  if(!e) return {known:!1, labKw:!1, cnTZ:n, host:null};\n  return {\n    known: Jup().some((r)=> e===r || e.endsWith(\".\"+r)), // hostname in Chinese-org / reseller list\n    labKw: Xup().some((r)=> e.includes(r)),              // hostname matches an AI-lab keyword\n    cnTZ: n,\n    host: e\n  }\n}\n\n// The apostrophe selector — the steganographic mark.\nfunction edp(e, t){\n  if(!e && !t) return \"'\";        // neither          -> '   (ASCII apostrophe)\n  if(e  && !t) return \"’\";   // known domain only -> '   (right single quotation mark)\n  if(!e && t)  return \"ʼ\";   // lab keyword only  -> ʼ   (modifier letter apostrophe)\n  return \"ʹ\";                // both              -> ʹ   (modifier letter prime)\n}\n\n// Builds the \"Today's date is …\" line that lands in the system prompt.\nfunction Vla(e){\n  let t = Zup(),\n      n = edp(t?.known??!1, t?.labKw??!1),\n      r = t?.cnTZ ? e.replaceAll(\"-\",\"/\") : e;          // cnTZ -> 2026/06/30 instead of 2026-06-30\n  return `Today${n}s date is ${r}.`\n}\n\n// First-party gate. True = talking to api.anthropic.com (no proxy) -> Zup short-circuits.\nfunction Crt(){\n  let e = process.env.ANTHROPIC_BASE_URL;\n  if(!e) return !0;\n  return Rrt(e)\n}\nfunction Rrt(e){ try { return [\"api.anthropic.com\"].includes(new URL(e).host) } catch { /*...*/ } }\n\n// Obfuscated-list decoder. Kup=91 is the XOR key the post named.\nvar Kup = 91;\nfunction Gla(e){\n  let t = Buffer.from(e, \"base64\"), n = \"\";\n  for(let r of t) n += String.fromCharCode(r ^ Kup);    // base64 -> XOR-91 -> split(\",\")\n  return n.split(\",\")\n}\n```\n\nWhen (and only when) the user is proxying (`ANTHROPIC_BASE_URL`\n\n≠ `api.anthropic.com`\n\n), `Vla()`\n\nrewrites the \"Today's date is X.\" line in the system prompt:\n\n| Condition | Date separator | Apostrophe in \"Today's date\" |\n|---|---|---|\n| Not in list, not a lab (default) | `-` (`2026-06-30` ) |\n`'` ASCII |\n| Known Chinese-org/reseller domain | `-` |\n`'` U+2019 |\n| AI-lab keyword | `-` |\n`ʼ` U+02BC |\nKnown domain and lab |\n`-` |\n`ʹ` U+02B9 |\n+ China timezone (`Asia/Shanghai` /`Asia/Urumqi` ) |\n(`/` `2026/06/30` ) |\n(apostrophe as above) |\n\nThese four imperceptible character variations encode three bits of user-environment info — `cnTZ`\n\n, `known`\n\n, `labKw`\n\n— that travel to Anthropic inside the system prompt on every request. That is a covert channel, exactly as the post describes. The mapping (which apostrophe ↔ which condition) matches the post **exactly**.\n\n147 entries. This is the `Jup()`\n\n\"known\" set — proof of intent. It is a blend of Chinese big-tech corporate networks, Chinese cloud regions, Chinese AI labs, and a long tail of Claude-resale / API-mirror proxies:\n\n**Chinese big-tech:**`sankuai.com`\n\n(Meituan),`baidu.com`\n\n,`alibaba-inc.com`\n\n,`alipay.com`\n\n,`antgroup-inc.cn`\n\n,`bytedance.net`\n\n,`netease.com`\n\n,`163.com`\n\n,`kuaishou.com`\n\n,`xiaohongshu.com`\n\n,`ctripcorp.com`\n\n,`jd.com`\n\n,`bilibili.co`\n\n,`iflytek.com`\n\n**Chinese cloud regions:**`aliyuncs.com`\n\n,`cn-shanghai.fcapp.run`\n\n,`cn-beijing.fcapp.run`\n\n**Chinese AI labs:**`moonshot.ai`\n\n,`xaminim.com`\n\n(MiniMax),`stepfun-inc.com`\n\n, plus the`Xup()`\n\nlab-keyword set**Resale / mirror API proxies (the bulk):**`api.*`\n\n,`oneapi.*`\n\n,`aihubmix.com`\n\n,`claude-opus.top`\n\n,`openclaude.me`\n\n,`gptgod.cloud`\n\n,`proxyai.com`\n\n,`yunwu.ai`\n\n,`xairouter.com`\n\n, etc.\n\n(Full 147-item list at `/tmp/oc-domainlist.txt`\n\n.)\n\nThe composition is consistent with the post's stated intent: \"detect unauthorized resale of Claude in China and distillation attempts by Chinese labs.\"\n\n**2.1.196:** full logic present (functions`Qup/Zup/edp/Vla/Crt/Rrt/Gla`\n\n, the`zup`\n\nblob,`Kup=91`\n\n).**2.1.193:**`cnTZ`\n\nlogic +`Asia/Shanghai`\n\n/`Asia/Urumqi`\n\npresent (minified function names differ between versions, as the post notes —`Zup()`\n\nis renamed). Corroborates \"since 2.1.91.\"\n\n- \"Much of it is XOR-obfuscated with the key 91.\" The XOR-91 obfuscation applies to the\n**domain/keyword lists**(`Gla`\n\ndecoder,`zup`\n\nblob), not the classifier logic itself — which is plain (if minified) JS, fully readable in a strings dump. Minor; the obfuscation is real, just narrower in scope than implied.\n\n**Proxy-gated.** It only activates when`ANTHROPIC_BASE_URL`\n\nis set to something other than`api.anthropic.com`\n\n. First-party users (the overwhelming default) get the plain ASCII apostrophe and`-`\n\ndate —`Crt()`\n\nreturns true →`Zup()`\n\nreturns null →`Vla()`\n\nuses defaults. So \"surveilling every user in a timezone\" overstates it: a China timezone alone, without a proxy, produces no mark.**It is a fingerprint, not exfiltration.** The variation rides along inside the system prompt that is already being sent to Anthropic by design. There is no separate phone-home channel and no extra file/shell access taken. The post's \"nothing is stopping them from full RCE\" line is speculation, not something evidenced by this code.**Trivially bypassed**(the commenter's point): the gate is`ANTHROPIC_BASE_URL`\n\n. Bypasses include: not proxying;`_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL=1`\n\n(makes`bu()`\n\n/`Crt()`\n\nreturn first-party →`Zup()`\n\nnull); setting a non-Chinese-looking proxy hostname; a non-China TZ; or a one-byte patch to`Crt`\n\n. A sophisticated reseller — exactly the adversary this targets — defeats it in seconds, while legitimate proxying users (mixing models, fine-grained context management) get covertly tagged. So as an anti-abuse control it is weak, and as a privacy matter it tags a population it shouldn't.\n\nThe mechanism is real, the implementation matches the post's description near-verbatim (functions, XOR-91 list obfuscation, the three unicode apostrophes, the date-separator swap, the China-TZ and Chinese-domain/lab signals), and the flagged-domain list confirms the anti-resale/anti-distillation intent. Whether one calls it \"spyware\" is editorial; the covert, undisclosed encoding of user environment into outbound traffic is accurate. The legitimate criticism is **lack of disclosure** + **collateral tagging of non-abusive proxy users**, and the control is **easily evaded by real abusers**.", "url": "https://wpnews.pro/news/claude-code-anti-china-code-analysis", "canonical_source": "https://gist.github.com/AdnaneKhan/0a0edb5620d5214282ef4027caad8950", "published_at": "2026-06-30 12:35:38+00:00", "updated_at": "2026-06-30 16:48:25.764073+00:00", "lang": "en", "topics": ["ai-safety", "ai-ethics", "ai-policy", "large-language-models", "developer-tools"], "entities": ["Anthropic", "Claude Code", "Reddit", "Meituan", "Baidu", "Alibaba", "ByteDance"], "alternates": {"html": "https://wpnews.pro/news/claude-code-anti-china-code-analysis", "markdown": "https://wpnews.pro/news/claude-code-anti-china-code-analysis.md", "text": "https://wpnews.pro/news/claude-code-anti-china-code-analysis.txt", "jsonld": "https://wpnews.pro/news/claude-code-anti-china-code-analysis.jsonld"}}