Auditing 153 Claude Code & Codex transcripts for #107757 User-Agent and URL email leaks (and filtering 259 [email protected] hits)
When anthropics/claude-code#107757 and #55743 hit the front page today (where Claude Code injects oauthAccount.emailAddress from ~/.claude.json into context and models copy that email into outbound User-Agent headers or
When anthropics/claude-code#107757 and #55743 hit the front page today (where Claude Code injects oauthAccount.emailAddress from ~/.claude.json into context and models copy that email into outbound User-Agent headers or query strings), I wrote a script to audit what my own coding agents had sent over the network across 153 local Claude Code and Codex CLI transcripts (1,928 deduplicated tool calls).
Two false-positive traps that bit my first script
-
The
[email protected]trailer inflation (259synthetic vs77real email hits): My first pass ran a standard email regex across~/.claude/projects/**/*.jsonland~/.codex/sessions/**/*.jsonland returned336email occurrences. I initially thought my sessions had leaked hundreds of personal and client addresses. Grouping by domain showed259of those336matches (77.1%) were[email protected]andexample.comstrings injected by Claude Code's ownCo-Authored-Bycommit trailer prompt. Filtering out synthetic trailer domains left77real email occurrences across8genuine domains (gmail.com53,mcxindia.com11,prince.sh4,adelev8.com4,nvidia.com2,aqr.com1). -
Loopback dev-server checks vs external egress (
19loopback vs11external): Extracting HTTP URLs from tool call inputs matched30requests,19of which (63.3%) were local health checks against127.0.0.1andlocalhost. Separating loopback traffic (EGL014) isolated the11real external requests (9toq.prince.sh,2togemini.google.com).
What actually leaked across 153 sessions
Once synthetic trailers and loopback requests were separated, the audit caught:
-
2outbound URL query email leaks (EGL008): Two tool calls passed?authuser=<REDACTED_EMAIL>@gmail.comdirectly in outbound URLs. -
1outbound file POST upload (EGL010): ABashcurlcommand uploaded a local payload file via HTTP POST to an external endpoint. -
3remote SSH MCP tunnels (EGL003): Three MCP servers in~/.claude.jsonwere configured to pipe tool arguments overssh root@<REDACTED_IP>. -
Active hardware and Statsig telemetry IDs (
EGL002):userID,machineID,cachedStatsigGates, andcachedGrowthBookFeatureswere active in~/.claude.jsonbecause neitherDISABLE_TELEMETRY=1norCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1was set in~/.claude/settings.json. -
153/153sessions (100%) injected my local macOS username path (/Users/<USER>) into prompt context (EGL005).
Running egressleak and blocking leaks in PreToolUse
I published the zero-dependency auditor as egressleak (npx egressleak):
npx egressleak
To block outbound email and token leaks deterministically without waiting for upstream CLI patches or trusting prompt instructions, run the emit-hook generator mode in npx egressleak. It outputs a zero-dependency Node.js PreToolUse guardrail script (~/.claude/hooks/egress-guard-hook.mjs) that inspects Bash, WebFetch, and WebSearch tool inputs and exits with code 2 if an outbound request includes a real email address in User-Agent, an ?authuser= / ?email= query parameter, or a secret API token (sk-, ghp_, AIza).
Limitations
-
egressleakinspects.jsonltranscripts and static config files on disk. If an agent executes a Python or Node script that constructs a destination URL dynamically at runtime without passing the URL or header in the tool call arguments, transcript replay cannot see that packet. - The generated
PreToolUsehook inspects tool call arguments (Bash,WebFetch,WebSearch) before execution, not child processes spawned inside an already-approved script file.
GitHub: https://github.com/princejain756/egressleak
npm: https://www.npmjs.com/package/egressleak
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.