正文 / 技术手记
AI 热点快报:Claude Code 把账号邮箱写进对外请求,正则补丁拦不住上下文里的 PII(2026-11-07)
11 月 5 日一份 GitHub issue 把 Claude Code 的隐私问题顶到 HN 首页(约 1,500 分):模型会把上下文里的账号邮箱当联系人,写进自己生成的 curl 的 User-Agent 发给第三方站点。Anthropic 11 月 3 日的 2.1.317 已经加了拦截,但钩子源码只认「邮箱字面量 + User-Agent 这个词」,多名 2.1.318 用户实测仍不拦截;团队成员 11 月 6 日承认真正的修法是把邮箱从上下文里删掉,下周初发版。
事件与背景#
11 月 5 日 22:13 UTC,用户 taylor-edwards 在 anthropics/claude-code 仓库开了一份 issue(#107757),标题是「User-Agent 头里的隐私泄露」,环境写的是 macOS + Claude Code 2.1.318。他的描述很直接:Claude Code 在做网络搜索时,未经同意就把他的邮箱放进了发给任意第三方的请求头,结果每天收到几十封诈骗邮件。这份 issue 现在仍是 open,94 条评论,标签是 bug / area:security;对应的 HN 讨论冲到 1,516 分、477 条评论。
机制不复杂。模型自己写 curl 命令时,会从上下文里取账号邮箱当「联系方式」塞进 User-Agent,形如 my-session-slug/1.0 <name@example.com>。诱因是 Wikipedia、SEC EDGAR 这类站点在机器人政策里要求脚本客户端留下联系邮箱,模型照做了。问题在于:站点要的是「一个可追责的联系人」,模型交出去的是「你的登录身份」。
时间线值得注意——补丁在爆料之前就已经发了:
- 7 月 25 日的 issue #81138 报的就是同一件事(账号邮箱被注入 system prompt,无同意、无披露),至今 open;
- 11 月 3 日发布的 v2.1.317 更新日志里写着「增加了一项检查,在 web 或 shell 工具调用把你的账号邮箱发到网络之前先询问」;
- 11 月 5 日 issue 爆火,多名 2.1.318 用户贴出实测:mod 已加载,但不拦截;
- 11 月 6 日 04:24 UTC,Claude Code 团队成员 lydia_hallie 在 HN 回复:会把账号邮箱从模型上下文里彻底移除,下个版本、下周初上线;同时承认现有 mod「仍然防不住所有情况,比如 Claude 自己写脚本再执行」。稳定通道当时还停在 2.1.311。
第三个独立来源让这条链更硬:Tin Analytics 检索自己的站点日志,10 月 31 日 13:20–15:46 UTC 之间有 5 个不同 User-Agent 抓取了它们那篇爬虫分析文章,每个都含脱敏邮箱,其中 3 个在抓文章前先请求了 robots.txt。这是日志计数,不是用户自述。需要说清楚的是:「诈骗邮件变多」仍是用户自己的因果主张,报告本身无法证明邮箱是从这里流出的。
来源(均已用 curl 验证返回 200):
- GitHub issue #107757(11/5) 与 issue #81138(7/25,同一问题的早期报告)
- HN 讨论 1,516 分 / 477 评论,含团队成员回复
- mods/privacy 的 README 与钩子源码
- v2.1.317 release notes
- Tin Analytics 的独立日志核查
为什么现在重要#
-
PII 的风险点不在「存哪儿」,而在「会不会被模型当素材写进它自己生成的命令」。邮箱本来是为了修另一个 bug(模型编造 @author 名字)才放进上下文的,结果变成了一个全量外发通道。影响:给 agent 的上下文应当按「随时可能出现在出站请求里」来设计,而不是按「只读参考」来设计。
-
用正则做隐私边界,漏是必然的。官方 mod 只有一条
tool.check钩子:Bash、PowerShell 或 Monitor 调用的输入里同时出现邮箱字面量和「User-Agent」这个词,才拒绝。源码里就是几个正则——UA 词、curl -A、wget -U、-User前缀。换个 header 名(-H "From: ...")、先写脚本再执行、做一次编码,都绕得过去。多位用户在 2.1.318 上实测「mod 加载了但不拦」,官方也承认脚本路径管不住。影响:deterministic guard 只能当减速带,当不了边界;真正的边界是数据不进入上下文。 -
三种说法互相打架,说明这是事后补的。release notes 说「先询问」,mod README 说「直接拒绝」,员工在 HN 说「会先问你」。同一个安全行为有三种描述,没有一份写清楚它到底拦什么、不拦什么。影响:读 agent 工具的隐私承诺要看实现而不是文案——这个 mod 的 README 只有 1.3 KB,读完就知道覆盖面在哪。
-
代价外溢给了不相干的第三方。收到邮箱的站点现在莫名持有一批用户的个人数据,而这些站点既没同意收集、也不知道该找谁负责。issue 里已经有人在提 GDPR(社区观点,不是法律结论)。影响:企业采购 agent 工具时,「出站请求带哪些标识」应该和「数据是否用于训练」并列为必问项。
-
正确的修法已经出现了,而且很朴素:把邮箱从 context 里删掉。不是加更强的过滤器、加更多正则,而是让模型根本拿不到这个字段——数据最小化优先于行为检测。这条对自建 agent 的团队同样成立:与其拦输出,不如别喂。
工程师/产品人今天能做什么#
-
先自查。
grep -r "User-Agent" ~/.claude/projects --include=*.jsonl,再用自己的邮箱过滤,看有没有外发记录、发给了哪些域名、时间跨度多长。有人在 issue 里报告扫出 53 次调用、跨 8 个会话(8 月 9 日到 11 月 1 日)。网关或 CDN 那一侧也可以反查:UA 里带@的请求。 -
升级到 2.1.317 或更高,并确认
/plugins里能看到cc-plugin-privacy@builtin。但先确认自己在哪个通道——爆料当天稳定通道还是 2.1.311。然后把 mod 当减速带:它拦得住最直白的那一类,拦不住脚本。 -
换身份,别用个人邮箱。给 agent 单独的角色邮箱(如
agent@yourdomain),git config user.email同样处理——7 月那个 issue 里的泄露就是从 git config 取到的。这一步能把「泄露后的损失」从个人收件箱降级成一个可丢弃的别名。 -
加自己的出站闸门。现成的有 whoami-guard 这类 hook(作者自测从 8/60 降到 0/60,属自报数据);更彻底的是把 agent 放进容器、只放行白名单出口,让任何带身份的 header 都出不去。
-
评估影响面。把已经外发过的域名列出来,判断是否需要通知、退订、加过滤规则;如果账号邮箱是工作邮箱,走一遍内部安全事件流程,别等对方先发现。
待观察#
- 「下周初」的版本是否真的把账号邮箱从上下文移除。issue 目前仍 open,稳定通道 2.1.311,承诺与实际之间还有几天窗口。
- 官方 mod 的覆盖面会不会补齐:现在只覆盖 Bash / PowerShell / Monitor 且必须出现 UA 词,其他 header、编码、脚本路径都还在外面。目前没有 CVE,也没有监管动作,GDPR 只是社区讨论。
- 其他 harness 是否也把账号身份塞进上下文。HN 上有人称 Codex CLI 的 UA 只有客户端、版本、系统和终端,但那是单点自查,不是审计;这类「身份进上下文」的设计在 agent 里很常见,需要各自验证。