DEV Community

Cover image for Auditing 153 Claude Code & Codex transcripts for #107757 User-Agent and URL email leaks (and filtering 259 noreply@anthropic.com hits)
Prince Jain
Prince Jain

Posted on

Auditing 153 Claude Code & Codex transcripts for #107757 User-Agent and URL email leaks (and filtering 259 noreply@anthropic.com 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 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

  1. The noreply@anthropic.com trailer inflation (259 synthetic vs 77 real email hits): My first pass ran a standard email regex across ~/.claude/projects/**/*.jsonl and ~/.codex/sessions/**/*.jsonl and returned 336 email occurrences. I initially thought my sessions had leaked hundreds of personal and client addresses. Grouping by domain showed 259 of those 336 matches (77.1%) were noreply@anthropic.com and example.com strings injected by Claude Code's own Co-Authored-By commit trailer prompt. Filtering out synthetic trailer domains left 77 real email occurrences across 8 genuine domains (gmail.com 53, mcxindia.com 11, prince.sh 4, adelev8.com 4, nvidia.com 2, aqr.com 1).
  2. Loopback dev-server checks vs external egress (19 loopback vs 11 external): Extracting HTTP URLs from tool call inputs matched 30 requests, 19 of which (63.3%) were local health checks against 127.0.0.1 and localhost. Separating loopback traffic (EGL014) isolated the 11 real external requests (9 to q.prince.sh, 2 to gemini.google.com).

What actually leaked across 153 sessions

Once synthetic trailers and loopback requests were separated, the audit caught:

  • 2 outbound URL query email leaks (EGL008): Two tool calls passed ?authuser=<REDACTED_EMAIL>@gmail.com directly in outbound URLs.
  • 1 outbound file POST upload (EGL010): A Bash curl command uploaded a local payload file via HTTP POST to an external endpoint.
  • 3 remote SSH MCP tunnels (EGL003): Three MCP servers in ~/.claude.json were configured to pipe tool arguments over ssh root@<REDACTED_IP>.
  • Active hardware and Statsig telemetry IDs (EGL002): userID, machineID, cachedStatsigGates, and cachedGrowthBookFeatures were active in ~/.claude.json because neither DISABLE_TELEMETRY=1 nor CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 was set in ~/.claude/settings.json.
  • 153/153 sessions (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
Enter fullscreen mode Exit fullscreen mode

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

  • egressleak inspects .jsonl transcripts 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 PreToolUse hook 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

Top comments (0)