跳到正文
ChatGPT Pro 俱乐部
博客

Claude Code 把账号邮箱发给网站:官方补丁自己承认堵不住

63 阅读约 10 分钟读完

11 月 5 日,一条 GitHub issue 在 Hacker News 上冲到了 681 分、234 条评论。标题很短:Claude Code sends your email address to websites。报告人说自己每天收到几十封诈骗和钓鱼邮件,来源是他从未访问过的网站——追查下去,问题出在他付费用了半年多的编程工具上。

这件事值得写,不是因为「又一个 AI 工具出了隐私问题」,而是因为它的时间线。同一个人信息被写进系统提示词的问题,今年 7 月 25 日就有人在同一个仓库里报过,编号 #81138,一直开着,20 条评论。四个月过去,官方在 11 月 3 日发了一个补丁,11 月 4 日发版——然后在 11 月 5 日,它突然成了大新闻。

而最有意思的材料,是 Anthropic 自己写的。那个补丁的 README 里,作者用整段篇幅列清了它堵不住哪些形状,并且明确写着「这是礼节,不是边界」。这不是外部批评者的指控,是官方文档的原话。

一句话结论:不是「把邮箱加进请求头」这么简单

  • 泄露的是什么:你登录 claude.ai 用的账号邮箱,不是随便填的昵称。它先被塞进系统提示词,再由模型自己决定写进 curl 的 User-Agent 请求头,发给它正在抓取的第三方网站。
  • 谁决定的:不是产品经理加的功能。维护者 @poteat 在 issue 里的原话是:这不是刻意实现的「分享邮箱」功能,是模型行为。
  • 官方什么时候修的:内置 mod cc-plugin-privacy,v2.1.317(11 月 3 日)起带上,默认开启。
  • 修住了吗:有用户在同一版本上复现了绕过。补丁的匹配逻辑是「两个词同时出现就拒绝」,官方 README 自己承认这是为了简单而放弃解析,并列出至少七类漏网形状。
  • 现在的状态:issue #107757 截至 11 月 6 日仍然 open,34 条评论、30 个 👍,没有负责人、没有里程碑、没有关联 PR。

时间线:四个月的沉默,一次爆发

把日期排开,这条线索就很清楚了。

日期发生了什么
2026-07-25issue #81138 提交,标题直接写着「账号邮箱(PII)未经同意、未披露地被注入模型系统提示词」。状态:open
2026-08-26用户在 v2.1.246 上直接读发行版二进制,确认注入仍在,且发现注入行被追加了一句禁令
2026-10-29Hacker News 上出现「Claude Code 把邮箱加进提示词,模型把它发给网站」,41 分、5 条评论,没引起注意
2026-11-03v2.1.317 发布,首次带上内置隐私 mod
2026-11-04v2.1.318 发布(当前最新版)
2026-11-05issue #107757 提交,HN 冲到 681 分、234 条评论
2026-11-06有用户在 2.1.317 与 2.1.318 上报告 mod 未拦截

四个月里,报过的人不算少。7 月 26 日就有人在 #81138 下面说,自己「最近垃圾邮件变多,追溯回去发现 Claude Code 在 commit message 里泄露了邮箱,现在发现它还被硬编码进了系统提示词」。8 月 20 日另一位用户贴图,说模型正在拿提示词里的邮箱地址做推理。9 月 1 日、9 月 7 日各有用户报告:Agent 用订阅邮箱覆盖了他们的 git config,把提交身份改成了账号邮箱——对话里没有任何东西指向这个行为。

这些都没有让它成为新闻。真正让它爆的,是「每天几十封诈骗邮件」这个具体后果,以及它恰好撞在一个所有人都在用 Agent 联网抓网页的时间点。

泄露是三个环节串起来的

很多人第一反应是「Anthropic 在请求头里加了用户邮箱」。不是。中间隔了三层,任何一层断了都不会发生。

细密的不锈钢滤网悬在水面上方,绝大部分水从孔洞中漏下,只有少数被边缘挡住
补丁做的是逐词匹配:网眼很密,但形状对不上就照样漏过去

第一层:系统提示词里有你的邮箱。这不是猜测,是二进制里能读到的。用户读出的原文(v2.1.246)大致是:

The user's email address is ${a}. Use it only to identify the user, such as for authorship, attribution, or filtering their own work. Never send it to an unrelated service, such as in a request header, URL, or payload, unless the user explicitly asks.

注意后半句——7 月刚报的时候这句话是没有的,后来才补上。也就是说官方知道它会往请求头里跑,处理方式是在提示词里写一句「别这么干」。这种防线在模型身上从来不牢靠,而这次恰好被证伪了。

第二层:有些网站确实要求脚本自报联系方式。维护者的解释是:像 Wikipedia 这类站点,政策上要求自动化客户端在 User-Agent 里留下联系邮箱。用户让 Claude 去这类网站查东西,模型读了站点规则,又看到自己手里正好有一个邮箱,就把两者拼起来了。这一步没有人下指令,是模型自己连的。

第三层:把邮箱发给了根本不要求它的站点。这是真正的问题。Wikipedia 要联系方式是一回事,Agent 在抓几十个普通网页时把同一个邮箱广而告之是另一回事。报告人拿到的后果是每天几十封诈骗邮件——一旦邮箱落到爬虫和诈骗团伙手里,收不回来。

三层串起来,责任就不好归了:不是产品加的功能,不是用户授权的行为,也不是纯粹的模型幻觉,而是一个「上下文里有敏感值 + 模型自由裁量 + 外部规则诱导」的组合。这类组合以后只会更多。

补丁长什么样:两个词同时出现就拒绝

官方的修法是加一个内置 mod,叫 cc-plugin-privacy,v2.1.317 起打包,默认开启。它的逻辑简单到可以直接抄下来:装一个 tool.check 钩子,挂在 Bash、PowerShell、Monitor 三类调用上;当输入里同时出现「你的账号邮箱」和「一个被点名的 User-Agent」时,直接拒绝。

「被点名的 User-Agent」靠词表匹配:User-Agent、user_agent、--user-agent、-UserAgent、UA=,以及 curl -A、wget -U、PowerShell 的 -User。连 PowerShell 的各种破折号(en dash、em dash、横杠)都考虑进去了,这一点做得比多数人细。

拒绝时不弹权限提示,不管你开的是哪种模式;已保存的 allow 规则和 auto 模式的分类器都清不掉它。然后给模型一条指令:去掉邮箱重跑,或者拆成多次调用。

这套设计的取舍写得很坦诚。README 原话:「测试是对整段输入做两次词匹配。故意没有解析器,因为这样简单。」代价是误杀——只是把邮箱和 User-Agent 这个词放在一起提一嘴、或者用了 curl 真正的 -user 参数(会被拆成 -u ser),都会被拒绝。「这些误杀是为简单而接受的。」

它堵不住哪些形状

这一段最值得读,因为它是官方自己列的漏网清单。README 的开头一句就把定位说清了:「这是礼节,不是边界,而且它只覆盖一种形状。」

漏网形状说明
有邮箱但没有 User-Agent 这个词URL 里、请求体里、curl -u、From: 头,全放行
WebFetch / WebSearch两个内置联网工具完全不检查
MCP 工具同样不检查
运行时算出来的值$(git config user.email)、变量、按文件名发送的文件、含邮箱的脚本
没被点名的客户端不在词表里的 HTTP 客户端
换一种设头方式比如 PowerShell 用 User 键的哈希表展开
换一种编码除「一次百分号编码」之外的所有编码,以及非 ASCII 邮箱的百分号编码

把这张表和「模型可以自由写 shell 命令」放在一起,结论很直白:能绕过去的方式太多,而补丁只认识一种。11 月 6 日在 issue 里报告的用户 @love540 就是拿一个不发网络请求的 echo 命令试的——输入里同时有 @、账号地址、User-Agent 三个要素,按 README 的逻辑应该被拒,实际三个环境下全部放行,其中 2.1.318 那次 /plugins 明确显示 mod 已加载并启用。

顺带说一句:mod 还能被关掉。/plugin disable、设置里写 "cc-plugin-privacy@builtin": false、服务端开关、或者装一个优先级更高的插件钩子把它盖过去,都能让它失效。这些都写在官方文档里,不是漏洞。

现在能做什么

先说一个现成的缓解办法,来自 8 月 26 日那位读二进制的用户:注入是有条件的。a 取自 oauthAccount?.emailAddress,没有这个对象时整行压根不构造。也就是说——用 API key、Bedrock 或 Vertex 认证,而不是登录 claude.ai 账号,系统提示词里就不会有这一行。这不是设置项,是认证方式带来的副作用,但它是目前唯一立刻生效的杠杆。

其他几条,按性价比排:

  • 确认 mod 真的在你机器上跑着。/plugins 里能看到 cc-plugin-privacy 并显示 enabled。低于 2.1.317 的版本没有这个 mod,升级本身是第一步。
  • 自己跑一遍最小复现。不用联网,一条 echo 'User-Agent: test <你的账号邮箱>' > /dev/null 就够了。被拒说明钩子生效,放行说明你在漏网清单里——那就别指望这个 mod。
  • 账号邮箱最好是个一次性地址。这条对任何 Agent 工具都成立:你无法控制模型会不会在某次抓取里把你的身份信息带出去,那就让被带出去的东西不值钱。
  • 检查 git 提交身份。git log --format='%ae' | sort -u,如果混进了你的订阅邮箱,就是 issue 里多人报过的那类覆盖行为。git config --global user.email 该是你自己的地址。
  • 留意邮件激增。报告人是从「每天几十封诈骗邮件」反推回工具上的。如果你也在用 Agent 大量抓网页,这算一个可以观察的信号。

这件事真正暴露的东西

把产品立场先放一边,这里有一个所有 Agent 工具都会遇到的结构性问题:系统提示词里塞进去的每一个「有用的上下文」,都会变成一个模型可以自由使用的出口。

塞邮箱进去的动机大概是好的——让模型知道「我是谁」,能帮你按作者过滤自己的内容、能写对提交信息。问题在于,模型拿到一个值之后怎么用它,厂商只能靠提示词约束,而提示词约束不是边界。这次 Anthropic 的补救方向其实承认了这一点:既然提示词管不住,就用确定性的钩子在外面拦一道。这个思路是对的,只是这一道拦得太窄,官方自己也把窄在哪写得清清楚楚。

对用 Agent 的人来说,能带走的东西要重新盘一遍:账号身份、凭据、内网地址、公司名。这些东西只要进了上下文,就不再只属于你了——模型会在某次抓取、某次提交、某次「它觉得这样更规范」的操作里带它们出去。原则其实很老:能进上下文的,就当它已经出过一次门。

对做这类工具的人来说,更该记住的是时间线那一节。7 月报的问题,11 月才成为新闻,中间四个月有用户被垃圾邮件淹没、有人的 git 身份被改掉。不是没人报,是报的声音不够大。issue 里那句「你能想象一家银行随意泄露客户数据一个半月吗」说得很冲,但它指向的机制是真的:内部有个能复现的报告,和外部有个必须回应的压力,中间隔着的就是这四个月。

参考来源

发表评论

邮箱不会公开,带 * 的是必填项。