# Claude Code email leak in User-Agent headers explained: why the model sent it, what the cc-plugin-privacy mod checks, and how to check and block it yourself

> Source: <https://theainewsreport.com/2026-11-06-claude-code-email-user-agent-leak-privacy-mod-explained.html>
> Published: 2026-11-06 15:45:56+00:00

# Claude Code email leak in User-Agent headers explained: why the model sent it, what the cc-plugin-privacy mod checks, and how to check and block it yourself

Claude Code sometimes wrote the signed-in user's email address into the User-Agent of web requests it built itself. We read the source of Anthropic's stopgap check, list what it does and does not cover, and give a script to scan your own sessions and a hook that blocks the address until the real fix ships.

**This explains reporting by**

[GitHub issue #107757 on anthropics/claude-code: Privacy violation in User-Agent header (November 5, 2026)](https://github.com/anthropics/claude-code/issues/107757).
Read the original first:

[https://github.com/anthropics/claude-code/issues/107757](https://github.com/anthropics/claude-code/issues/107757)

## In one minute

- Claude Code put the signed-in account's email address in the model's context. When the model wrote its own curl call or script, it sometimes used that address as a contact in the User-Agent header.
- Anthropic says the next release, expected early next week, removes the email from the model's context. Until then, 2.1.317 and later carry a built-in mod called cc-plugin-privacy.
- The mod only reads Bash, PowerShell and Monitor calls, and only refuses one that holds your address AND names a User-Agent. Web tools, scripts written to disk, other headers and values read at run time all pass.
- On November 6 the npm stable channel was still on 2.1.311, which has no mod at all. Several users also report the mod loaded but did not fire on 2.1.317 and 2.1.318.
- You can check your own history with a short scan of ~/.claude/projects and block the address yourself with a PreToolUse hook. Both are below and were tested on a real install.

## What happened

On November 5, 2026 at 22:13 UTC, a user opened issue 107757 on the Claude Code GitHub repository. They wrote that Claude Code, version 2.1.318 on macOS, had put their email address in the User-Agent header of web requests without asking, and that they now get scam email every day. By the morning of November 6 the issue had more than 750 reactions and 87 comments, and its Hacker News thread passed 1,390 points.

An Anthropic contributor, mpoteat, replied within the hour that a built-in mod called cc-plugin-privacy blocks this in 2.1.317 and later, on by default. Early on November 6 UTC, Lydia Hallie, who works on Claude Code, wrote on Hacker News that the team is removing the account email from the context Claude Code gives the model, in a release expected early next week, and apologized.

## Why a model would put your email in a header

Hallie's account: users had reported Claude making up names in places like @author tags, so Claude Code began giving the model the signed-in account's email. When Claude then wrote a command itself, such as a curl call, it sometimes used that address as the contact in the User-Agent.

There is a real reason a script would want a contact there. Wikimedia's User-Agent policy asks scripted clients to identify themselves and give a way to reach the operator, and it accepts an email address. The SEC asks automated EDGAR clients to send a User-Agent with a company name and an admin email. A model that has been told to be a polite client, and has exactly one email address in front of it, fills in that one.

It was not only the built-in web tools. One commenter scanned his own transcripts and reported 53 calls across 8 sessions that put his address in a User-Agent, almost all from subagents writing their own curl -A lines. Another found the model also invents a product name for the User-Agent from the project it is working on, so the header can tie your identity to your work. Both are user reports we did not reproduce.

## What the privacy mod checks, read from its source

Anthropic published the mod's source on November 6 under mods/privacy in the claude-code repository. It registers one tool.check hook, and it only runs for three tools: Bash, PowerShell and Monitor.

- If a lower layer already denied the call, it keeps that denial.
- If the call's input has no @ sign and no %40, it lets the call through without looking further.
- Otherwise it reads the account address from the session and lowercases both. It also decodes one pass of percent-encoding.
- It refuses the call when the input holds the address AND names a User-Agent: the words User-Agent, user_agent, --user-agent or UA=, or a client flag such as curl -A, wget -U or PowerShell's -UserAgent.

The refusal raises no prompt. Its README says a saved allow rule and auto mode's classifier do not clear it, and it describes the whole check as two word matches with no parser, on purpose.

## What it does not check, by its own README

The README calls the mod a courtesy, not a boundary, and lists what passes. These are its own words turned into a list:

- WebFetch, WebSearch and every MCP tool. None are checked.
- The address anywhere but a User-Agent: in a URL, a request body, curl -u, a From: header or any other header name.
- A value computed at run time, such as $(git config user.email), a shell variable, or a file sent by name.
- A script that holds the address. If the model writes the address into fetch.py with Write or Edit and then runs python3 fetch.py, no checked input ever contains it.
- Encodings other than one pass of percent-encoding, and clients the regex does not name.
- It is off after /plugin disable, after a server-side switch, or when an installed plugin's hook overrules it.

Two things do not line up. Hallie wrote on Hacker News that the mod asks you before Claude runs a web tool call. The published source has no prompt, and its README says web tools are not checked. And on 2.1.317 and 2.1.318, users on macOS and Windows posted tests where the mod showed as loaded yet still let a curl -A call with their own address, aimed at a .invalid host, run. Anthropic had not answered those reports in the issue by 08:30 MST on November 6.

## Which version you are on matters

Hallie noted the stable channel was still on 2.1.311. We checked npm on November 6: the stable tag is 2.1.311, latest is 2.1.318, and next is 2.1.319. 2.1.317 was published on November 2. So anyone who pins the stable channel has the email in context and no mod at all.

```
claude --version
npm view @anthropic-ai/claude-code dist-tags
# on November 6, 2026: stable 2.1.311, latest 2.1.318, next 2.1.319
```

Inside Claude Code, open /plugins and confirm cc-plugin-privacy shows as installed and enabled.

## Check whether it happened to you

Claude Code keeps each session as a JSON Lines file under ~/.claude/projects. This scan reads your account address from ~/.claude.json, then lists every session file where a single tool call holds that address and a User-Agent word or a -A flag. It prints paths and a count, never the address. We ran it on one real install and it found matches, so the risk is not only theoretical.

```
# scan.py: list Claude Code sessions where a tool call held your account email and a User-Agent.
# It prints file paths and a count, never the address itself.
import json, os, glob, re
email = json.load(open(os.path.expanduser("~/.claude.json"))).get("oauthAccount", {}).get("emailAddress", "").lower()
files = 0
for f in glob.glob(os.path.expanduser("~/.claude/projects/**/*.jsonl"), recursive=True):
    for line in open(f, errors="ignore"):
        low = line.lower()
        if '"tool_use"' in line and email and email in low and re.search(r"user[-_]?agent|\s-a\s", low):
            files += 1
            print(f)
            break
print(files, "session file(s) with a tool call that holds your address and a User-Agent")
```

A hit means the model wrote such a call. It does not prove the request reached a server, since a call can fail or be refused. Open the file and read the call to see the host.

## Block it yourself until the fix ships

Claude Code hooks run your own code before a tool call. For a PreToolUse hook, exit code 2 blocks the call, and whatever the hook prints to stderr goes back to Claude as the reason. This hook is deliberately blunt: it refuses any call whose input holds your account address or your global git email, in any header, body or file, plus any call that reads git's user.email.

``` bash
#!/usr/bin/env python3
# ~/.claude/hooks/no-my-email.py: refuse any tool call that holds my email address.
import json, os, subprocess, sys
event = json.load(sys.stdin)
text = json.dumps(event.get("tool_input", {})).lower()
mine = set()
try:
    mine.add(json.load(open(os.path.expanduser("~/.claude.json")))["oauthAccount"]["emailAddress"].lower())
except Exception:
    pass
git = subprocess.run(["git", "config", "--global", "user.email"], capture_output=True, text=True).stdout.strip().lower()
if git:
    mine.add(git)
if any(m and m in text for m in mine) or "user.email" in text:
    print("Blocked: this call contains my email address. Ask me first.", file=sys.stderr)
    sys.exit(2)
sys.exit(0)
```

Register it in ~/.claude/settings.json. A matcher made only of names and | is a list of exact tool names:

```
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|PowerShell|Monitor|Write|Edit|WebFetch",
        "hooks": [
          {"type": "command", "command": "python3 ~/.claude/hooks/no-my-email.py", "timeout": 5}
        ]
      }
    ]
  }
}
```

We tested it with a curl -A call holding the address (blocked, exit 2), the same call without it (allowed, exit 0), and a Write of a Python script with the address upper-cased in a User-Agent (blocked). It does not see MCP tools, a value a script fetches from somewhere else at run time, or a request that ignores both. It will also block harmless calls that mention your address, which is the trade we chose.

## What the real fix changes, and what it will not

Removing the email from the model's context takes away the address the model has been pasting. It does not stop a model from reading your git config or a dotfile and using what it finds; one commenter says that is exactly how Claude got his address. It also does nothing about the made-up product names in User-Agents that describe your project. For those, a hook like the one above, or a network rule on outbound requests, is still the control you own.

## Who is affected

| Case | Status | 
|---|---|
| Claude Code before 2.1.317, signed in with an account (includes the npm stable channel, 2.1.311, on November 6) | Email is in the model's context and no built-in check runs. Update, or add your own hook. | 
| Claude Code 2.1.317 to 2.1.319 | Shell calls that hold your address and name a User-Agent are refused. Web tools, MCP tools, scripts and other headers are not checked, and some users report the check not firing. | 
| The next Claude Code release, expected early next week per Anthropic | Removes the account email from the model's context. Not shipped as of November 6, 08:30 MST. | 

## What to do

- Run claude --version. If you are below 2.1.317, update now.
- Open /plugins and confirm cc-plugin-privacy is installed and enabled.
- Run the scan above on every machine where you use Claude Code, and read any hit to see which host it went to.
- Add the PreToolUse hook above, and test it with a harmless echo that holds your address.
- If you do not want your real address in git config, set user.email to your Git host's noreply address.
- Watch the Hacker News thread or the issue for Anthropic's update when the fix ships.

## What is still unknown

- How many users or requests were affected. Anthropic has given no count.
- Whether sessions signed in with an API key, rather than a claude.ai account, ever had the email in context.
- Why the mod did not fire in the user tests posted for 2.1.317 and 2.1.318. Anthropic has not confirmed or explained those reports.
- Which description of the mod is right: Hallie's (it asks before web tool calls) or the published source and README (no prompt, web tools unchecked). We went with the source.
- Whether the spam users describe came from these headers. That link rests on their own logs and timing.
- The release date of the fix. Early next week is Anthropic's estimate.
- No CVE had been assigned as of November 6.

## Sources

[AI News Report](https://theainewsreport.com/)· every headline, every morning.
