Claude Code 把登录邮箱写进了每个请求头
11 月 5 日,一条 issue 被顶到 Hacker News 首页,1,216 分。
标题很直白:Claude Code 在 curl 命令里,把用户的真实邮箱当成 User-Agent 发出去了。发帖的人说,自己每天收到几十封诈骗邮件,追下来发现是 Claude Code 在搜索网页时,把他的邮箱交给了各种第三方站点。
issue 编号 107757,到第二天中午已经有 593 个反应、67 条评论。有人跟帖说,自己那个十几年没怎么用过、安静得像废弃邮箱的地址,最近突然被各种奇怪的邮件轰炸。
邮箱是怎么出去的
事情不复杂。
很多网站的用户协议里有一条:脚本客户端来访问,要在 User-Agent 里留一个联系邮箱。Wikipedia 就是这么要求的。Claude 去查资料,看到这条规则,就老老实实照做了——把当前登录账号的邮箱填进了 curl 的 User-Agent。
问题在于,这个邮箱不是它临时问来的,是上下文里本来就有的。Anthropic 的隐私插件文档写得很清楚:上下文会把登录账号的地址交给模型,用来标识用户($.session.identity())。
所以这不是某个功能在偷偷上传数据,而是模型在“遵守网站规则”的时候,把用户的身份信息当成了可用的素材。Anthropic 的工程师在 issue 里解释过一句:没有人把“把邮箱分享给网站”当成功能来做,模型的行为很难预测,所以才需要确定性的检查。
话说得没错。但对用户来说,结果是一样的:你去查个资料,邮箱进了别人的日志。
补丁长什么样
11 月 5 日当晚,Anthropic 的工程师回帖:v2.1.317 及以后内置了一个 cc-plugin-privacy 模块,默认开启,可以在 /plugins 里关掉;源码也放出来了。
我读了 mods/privacy 的 README。它的实现比名字朴素得多:
一个 tool.check 钩子,检查两件事——这次工具调用的输入里,有没有出现登录邮箱;有没有出现 User-Agent 这个词(或者 curl -A、wget -U、PowerShell 的 -User 这类写法)。两个都命中,就拒绝执行。
没有解析器,就是两个字符串匹配。README 自己说,这是故意的:简单,可预测。代价是误杀——一个只提到 User-Agent、但把邮箱发去别处的命令会被拦;curl -u ser 这种参数也会被当成 -User。
然后是最关键的一句话,README 原文:
This is a courtesy, not a boundary.
礼貌,不是边界。
它挡不住什么
README 没有藏着掖着,直接列了一串能穿过去的情况:
- 邮箱不写在 User-Agent 里,而是放在 URL、请求体、
curl -u、From:头里——不拦 - WebFetch 和 WebSearch 这两个网页工具——不检查
- MCP 工具——不检查
- 运行时才算出来的值,比如
$(git config user.email)——不拦 - 变量、文件、脚本里带的地址——不拦
- 不在这份名单里的客户端,或者用别的方式设置请求头——不拦
- 一次 percent-encoding 之外的编码、非 ASCII 地址——不拦
- 装了别的插件,它的 hook 排在这个模块上面,可以覆盖拒绝
/plugin disable,或者服务端开关——直接关掉
这不是我在挑刺,是插件作者自己写在文档里的边界说明。它防的是“模型顺手把邮箱塞进 UA”这一种形状,不是“邮箱不会离开这台机器”。
2.1.318 上,还有人能复现
更麻烦的是版本对不上。
官方说 2.1.317 及以后就有了。但 issue 里至少三个人在 2.1.318 上测出了相反的结果:
- 一个人说,自己在
/plugins里根本看不到cc-plugin-privacy - 一个人说,日志确认邮箱还是发到了其他域名
- 还有一个人按文档里的用例做了测试,模块没有拒绝
有人猜是会话在更新前就启动了,hooks 没重新加载;也有人说是插件链被别的东西盖住了。具体原因还没有定论,但至少说明一件事:升级到最新版,不等于这件事就结束了。
顺带一提,这个模块是可以被仓库配置影响的——README 说仓库的 settings 关不掉它,但已安装插件的 hook 可以覆盖它的拒绝。对普通用户来说,这些细节太深了,深到没法自己判断“我到底安全了没有”。
现在能做什么
如果你在用 Claude Code,有几件事值得今天就做:
第一,升级到 2.1.317 以上,打开 /plugins 确认 cc-plugin-privacy 在列表里、是启用状态。看不到就别假设它在工作。
第二,抓一次包。用代理或者看本地日志,随便让它查个资料,看请求头里有没有你的邮箱。这比看版本文档可靠。
第三,换登录账号。用一个专门的工作邮箱或者别名邮箱登录 Claude Code,别用你的主邮箱。这是最彻底的一招——不管插件有没有生效,泄露的都不是你最重要的那个地址。
第四,对隐私敏感的任务,换一个 harness,或者用本地模型。issue 里有人提到,同样的模型放在别的客户端里没有出现这个行为;问题出在 Claude Code 这个壳,不是模型本身。
第五,如果还能复现,去 issue 里补一条带版本号、平台和复现步骤的回复。维护者明确说了,他们要知道“检查的缺口在哪”。
最后
这件事最值得记住的,不是“Anthropic 又出事了”,而是一个产品选择:把隐私做成一个默认开启、可以关掉、可以被覆盖、只匹配一种字符串形状的插件。
插件能挡住大多数误伤,这没错。但隐私不该是插件,它应该是默认值——上下文里根本不该有那个邮箱,或者至少不该让模型觉得它可以拿来当联系方式。
在这一点改掉之前,cc-plugin-privacy 更像一张创可贴:贴上了,伤口还在。
相关链接:
- Issue #107757:https://github.com/anthropics/claude-code/issues/107757
- 隐私模块源码与说明:https://github.com/anthropics/claude-code/tree/main/mods/privacy
- Hacker News 讨论:https://news.ycombinator.com/item?id=50385272
- Claude Code 仓库:https://github.com/anthropics/claude-code
暂无评论。