Skip to content

Back to the catalog

Second Time, Same Sandbox: Another Anthropic Claude Code Network Sandbox Bypass Enables Data Exfiltration
oddguan.comwriteup

Second Time, Same Sandbox: Another Anthropic Claude Code Network Sandbox Bypass Enables Data Exfiltration

Security researcher Aonan Guan discloses a second Claude Code network sandbox bypass: the SOCKS5 proxy that enforces wildcard domain allowlists (e.g. *.google.com) hands raw hostnames from CONNECT requests into a JavaScript endsWith() check with no canonicalization, so an attacker-controlled hostname like attacker-host.com\x00.google.com passes the JS filter but gets truncated at the null byte by libc's getaddrinfo, causing the OS to actually dial the blocked host. Every Claude Code release from 2.0.24 (sandbox GA, 2025-10-20) through 2.1.89 was affected until a silent fix in sandbox-runtime 0.0.43 / Claude Code 2.1.90 (2026-04-01); combined with prompt injection this let sandboxed agent code exfiltrate credentials and internal data over a channel egress logs typically don't inspect. It follows the earlier CVE-2025-66479 (allowedDomains: [] read as allow-everything) and highlights Anthropic's pattern of shipping fixes with no CVE, advisory, or changelog note.

TL;DR Null-byte hostname smuggling (attacker-host.com\x00.google.com) let sandboxed Claude Code processes bypass wildcard network allowlists and exfiltrate data for 5.5 months, silently patched in v2.1.90 with no CVE or advisory.
Document

What it is

A SOCKS5 hostname null-byte injection in Anthropic Claude Code's network sandbox (the egress proxy provided by the sandbox-runtime library, versions ≤ 0.0.42). An attacker running code inside the sandbox can reach any blocked host despite a wildcard allowlist. It is the second complete bypass of this sandbox by an outside researcher; the first was CVE-2025-66479 (empty allowedDomains: [] misread as "allow everything").

How it works

OS-level enforcement (sandbox-exec on macOS, bubblewrap on Linux) correctly pins the sandboxed process to localhost. Egress decisions are delegated to a SOCKS5 proxy running on the host with full network privileges — that is where the flaw lives. The proxy hands the raw DOMAINNAME bytes from the CONNECT request straight into a JS endsWith() check with no canonicalization:

// sandbox-runtime <= 0.0.42
function matchesDomainPattern(hostname: string, pattern: string): boolean {
  if (pattern.startsWith('*.')) {
    const baseDomain = pattern.substring(2)
    return hostname.toLowerCase().endsWith('.' + baseDomain.toLowerCase())
  }
  return hostname.toLowerCase() === pattern.toLowerCase()
}

JavaScript treats \x00 as an ordinary UTF-16 code unit; libc getaddrinfo treats it as a C string terminator. So attacker-host.com\x00.google.com passes endsWith('.google.com'), while the OS resolves and dials attacker-host.com.

sequenceDiagram
  participant P as Sandboxed process
  participant Proxy as SOCKS5 proxy (JS filter, host)
  participant DNS as getaddrinfo (libc)
  P->>Proxy: CONNECT attacker-host.com\x00.google.com
  Note over Proxy: endsWith('.google.com') → ALLOW
  Proxy->>DNS: resolve(same string)
  Note over DNS: terminates at \x00 → attacker-host.com
  DNS-->>Proxy: A record for attacker-host.com
  Proxy->>P: blocked host reached — exfil channel open

Preconditions / Affected

  • Claude Code with sandbox mode enabled and a wildcard allowedDomains allowlist (e.g. *.google.com).
  • Attacker capability to run code in the sandbox — realistically via prompt injection (e.g. a hidden instruction in a GitHub issue comment Claude Code reads).
  • Every release from v2.0.24 (sandbox GA, 2025-10-20) through v2.1.89 was vulnerable to at least one of the two bugs.

What to do

  • Upgrade to v2.1.90 (released 2026-04-01), which silently fixed the null-byte injection. Note: v2.0.55 (2025-11-26) fixed Finding 1 but still shipped this bug.
  • Do not rely on the allowlist as a hard boundary on the affected versions; there was, per the author, no release where the sandbox actually enforced egress correctly.

Caveats

  • No Claude Code advisory, changelog note, or CVE was issued for either finding; CVE-2025-66479 was filed against the sandbox-runtime library, not the product users configure. Users could only learn of exposure by reverse-engineering cli.js or reading this post.
  • Fixes were "silent," so the exact patched commit is not independently confirmed here beyond the stated version.

Organisations named here

  • CWE-158
  • CWE-436
  • HackerOne #3646509

CVEs named here

  • CVE-2025-66479
  • CVE-2025-68143

Technologies named here

  • sandbox-runtime
  • Claude Code
  • @pondwader/socks5-server
  • sandbox-exec / bubblewrap
  • test-block.mjs / test-not-block.mjs
  • HackerOne
  • NVD / GitHub Advisory Database
  • Node.js
  • npm

Techniques named here

  • SOCKS5 hostname null-byte injection
  • Parser differential / interpretation conflict
  • Improper neutralization of null byte
  • Configuration-semantics bug