[BUG] Allow network egress - All domains' setting not reflected in session proxy JWT

Status Open
Maintainer reply None cached
Activity 4 comments · opened Mar 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Summary

When Allow network egress is enabled with Domain allowlist set to All
domains
, the egress proxy still enforces a restrictive hardcoded allowlist of
specific domains rather than permitting all outbound traffic.

Actual Behavior

The egress proxy returns 403 Forbidden with x-deny-reason: host_not_allowed.

Inspecting the proxy's https_proxy JWT (visible in curl -v output) reveals
the token contains an explicit allowed_hosts field listing specific well-known
package registries and development services — not a wildcard. The "All domains"
setting is not reflected in the issued JWT.

Additional Context

  • The setting has been configured for multiple weeks, ruling out a propagation delay
  • Starting a new session does not resolve the issue — the JWT is still minted

with the restrictive allowlist

  • The JWT has iat/exp fields confirming it is issued at session start,

suggesting session initialization does not correctly read the current allowlist policy

Impact

Users with legitimate use cases requiring access to private/self-hosted
infrastructure (e.g., internal services, private registries, on-prem tooling)
are blocked even after explicitly configuring unrestricted egress access.

What Should Happen?

All outbound domains should be accessible, as indicated by the UI message:
"Claude can access all domains on the internet."

Error Messages/Logs

$ curl -v --max-time 10 https://<custom-domain>/api/v1/version

* Uses proxy env variable https_proxy == 'http://...jwt_<token>...'
* Trying 21.0.0.191:15004...
* Connected to 21.0.0.191 port 15004
* CONNECT tunnel: HTTP/1.1 negotiated
* Establish HTTP proxy tunnel to <custom-domain>:443

> CONNECT <custom-domain>:443 HTTP/1.1

< HTTP/1.1 403 Forbidden
< x-deny-reason: host_not_allowed
< server: envoy

* CONNECT tunnel failed, response 403
curl: (56) CONNECT tunnel failed, response 403




{
  "iss": "anthropic-egress-control",
  "iat": 1773591510,  // 2026-03-15 16:18:30 UTC
  "exp": 1773605910,  // 2026-03-15 20:18:30 UTC
  "allowed_hosts_count": 205,
  "allowed_hosts": ["java.net", "registry.yarnpkg.com", "get.rvm.io", "k8s.io",
                    "*.googleapis.com", "java.com", "www.rust-lang.org", ...],
  "wildcard_entries": ["*.googleapis.com", "*.nixos.org", "*.sentry.io",
                       "*.microsoftonline.com", "*.amazonaws.com", ...],
  "use_egress_gateway": true
}

Steps to Reproduce

  1. In Claude Code settings, enable Allow network egress
  2. Set Domain allowlist to All domains
  3. Save settings
  4. Start a new conversation session
  5. Attempt to make an outbound HTTP request to a domain not on the standard

package registry allowlist (e.g., a private self-hosted service)

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude 1.1.6679 (f8f4ff) 2026-03-13T18:26:03.000Z

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

PowerShell

Additional Information

Key observation: allowed_hosts contains a fixed list of 205 specific domains/patterns. There is no * wildcard, no allow_all: true flag, and no indication that the "All domains" UI setting is reflected anywhere in the token. A custom self-hosted domain is rejected with host_not_allowed despite the org setting being configured to "All domains" for over two weeks and across multiple reinstalls/sessions.

View original on GitHub ↗

3 Comments

cameron-bales-telus-health · 4 months ago

Adding some observations that might help narrow this down:
I'm running Cowork on macOS. A few data points:
Subdomain asymmetry on GitHub:

github.com (main web interface) — accessible via WebFetch ✅
raw.githubusercontent.com — blocked ❌
api.github.com — blocked ❌

This suggests the hardcoded allowlist includes github.com but not its subdomains, which would be consistent with the JWT containing exact hostnames rather than wildcard entries like *.github.com.
Government/public-sector domains blocked:

ontario.ca (Ontario government website, Canada) — blocked ❌

This is a legitimate use case — fetching publicly available government documents and schedules.
Regression note:
I had a scheduled task (running in Cowork) that successfully fetched a page on ontario.ca for several weeks. It stopped working at some point — I don't have the exact date, but this suggests the allowlist may have become more restrictive over time, not less.
Environment: Cowork macOS, April 2026. Network egress set to "All domains" in Admin → Capabilities — this setting has no effect on the proxy behaviour as described in this issue.

MarcinPrDev · 21 days ago

Confirming this on Claude Code on the web (cloud sessions, both scheduled routines and manual runs), 2026-08-09. Same root cause, slightly different surface — posting the raw proxy exchange since it differs from the JWT symptom above.

Configuration: Allow network egress enabled, Domain allowlist = All domains, UI states "Claude can access all domains on the internet." Individual (non-Team) account.

Result: every non-package-manager host is rejected at CONNECT.

* Connected to 127.0.0.1 (127.0.0.1) port 37813
* CONNECT tunnel: HTTP/1.1 negotiated
> CONNECT www.litcharts.com:443 HTTP/1.1
> Proxy-Connection: Keep-Alive
< HTTP/1.1 403 Forbidden
< Content-Length: 36
* CONNECT tunnel failed, response 403

The 36-byte body of the CONNECT response (read off a raw socket):

request rejected: host not permitted

Note: in this environment the proxy sends no x-deny-reason header — the denial reason exists only in that body, which makes the failure harder to diagnose than the header-based case described in the original report.

WebFetch surfaces it as:

{"error_type":"EGRESS_BLOCKED","domain":"www.litcharts.com",
 "message":"Access to www.litcharts.com is blocked by the network egress proxy."}

$HTTPS_PROXY/__agentproxy/status corroborates:

{"enabled": true, "port": 37813, "selective": false,
 "recentRelayFailures": [
   {"kind":"connect_rejected","detail":"gateway answered 403 to CONNECT (policy denial or upstream failure)","host":"www.litcharts.com:443"},
   {"kind":"connect_rejected","host":"www.gutenberg.org:443"},
   {"kind":"connect_rejected","host":"wolnelektury.pl:443"}]}

Tested hosts: www.litcharts.com, www.gutenberg.org, wolnelektury.pl — all 403. Control: pypi.org/simple/ returns 200, but only because it sits in NO_PROXY and bypasses the filtering proxy entirely, so it is not evidence of working egress. The effective allowlist appears hardcoded to npm/PyPI/crates/Go/GitHub plus Anthropic domains, regardless of the account setting.

Impact: agents that rely on WebFetch to read primary sources cannot fetch a single one in cloud sessions. WebSearch still works, but returns titles/URLs/snippets only — the pages behind those URLs are unreachable. For any workflow whose correctness depends on reading sources rather than search snippets, unattended cloud runs silently degrade to snippet-based output. In our case this produced a measurable ~12% error rate on checkable claims versus the same pipeline run locally, where WebFetch works normally.

Happy to supply further diagnostics from a cloud session if useful.

MarcinPrDev · 21 days ago

Follow-up, ruling out the obvious alternative explanation: the target sites are not blocking the requests.

Same three URLs, same WebFetch tool, run from a local Claude Code session minutes after the cloud test — all three succeed:

| URL | cloud session | local session |
|---|---|---|
| https://www.litcharts.com/lit/hamlet | EGRESS_BLOCKED / CONNECT 403 | 200, page content returned |
| https://www.gutenberg.org/cache/epub/1524/pg1524.txt | EGRESS_BLOCKED / CONNECT 403 | 200, full text returned |
| https://wolnelektury.pl/katalog/lektura/hamlet.html | EGRESS_BLOCKED / CONNECT 403 | 200, metadata returned |

The only variable is the execution environment.

Two further points that rule out site-side blocking on their own:

  1. The 403 is answered by the proxy, not the origin. It arrives in response to CONNECT www.litcharts.com:443 sent to 127.0.0.1:37813, i.e. before any TLS handshake with the origin server exists. A remote host cannot answer a CONNECT — that exchange is strictly between client and proxy.
  2. The denial text is policy wording, not a WAF/bot page: request rejected: host not permitted, and the harness classifies it as EGRESS_BLOCKED with the message "blocked by the network egress proxy".

For completeness: in the same local session, verification agents fetched dozens of pages from folger.edu, shakespeare.mit.edu, pl.wikisource.org and wolnelektury.pl without a single block — so this is not rate limiting or bot detection against this client either.

Showing cached comments. Read the full discussion on GitHub ↗