[FEATURE] Decouple WebFetch domain permissions from sandbox network allowlist

Resolved 💬 1 comment Opened Apr 26, 2026 by Amund211 Closed May 28, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

TL;DR

I want to

  • Allow the agent to use the WebFetch tool for certain domains without approval.
  • Restrict arbitrary network access inside the sandbox to a minimal subset.

I am very lenient with what I allow for WebFetch, as I regard that as relatively low risk, but I am much more vigilant when setting sandbox.network.allowedDomains, as I don't want the agent to do any mutations over the network without my approval.
Currently there doesn't seem to be any separation between the two, as adding WebFetch(domain:github.com) to permissions.allow also allows arbitrary network requests from inside the sandbox to that domain (not just actual WebFetch tool calls). This leads to the agent being able to do e.g. git push without my approval.

Full description

Today, permissions.allow["WebFetch(domain:foo)"] and sandbox.network.allowedDomains are merged: granting WebFetch access to a domain implicitly grants sandboxed Bash network access to the same domain.

This blocks a default-deny security posture for sandboxed Bash. WebFetch is read-only and the model's output is reviewed by the user; sandboxed Bash can run arbitrary commands that touch files and external APIs. Coupling them means I cannot say "the sandbox may only reach domain X" without also losing the ability to pre-approve WebFetch for unrelated domains.

The only workaround is enumerating every WebFetch domain in sandbox.network.deniedDomains to break the implicit contribution. That's listed-deny, not default-deny: every new WebFetch(domain: <domain>) permission must be paired with a matching deny entry, or sandbox access silently leaks. The two layers cannot be independently reasoned about.

This problem also surfaces in the opposite direction (#38735: WebFetch(domain:X) in permissions.deny punches through and blocks ALL sandbox network), which confirms the coupling is bidirectional and not just a convenience default.

Proposed Solution

Add a setting that makes sandbox.network.allowedDomains the sole authority for sandbox network access - disabling the implicit contribution from WebFetch(domain: <domain>) permission rules.

Suggested shape:

{
  "sandbox": {
    "network": {
      "strictAllowlist": true,
      "allowedDomains": ["proxy.golang.org"]
    }
  },
  "permissions": {
    "allow": [
      "WebFetch(domain:github.com)"
    ]
  }
}

With strictAllowlist: true:

  • WebFetch can fetch github.com (permission rule still applies - WebFetch runs outside the sandbox)
  • Sandboxed Bash can ONLY reach proxy.golang.org (because allowedDomains is the sole source)
  • No parallel deniedDomains list to maintain

Default for strictAllowlist should be false to preserve current behavior.
Other possible names for the setting: ignoreWebFetchDomains: true, webFetchDomainsContributeToSandbox: false.

Alternative Solutions

  1. sandbox.network.deniedDomains enumeration (current workaround) - must add every WebFetch domain to the deny list; error-prone and grows unboundedly.
  2. Custom HTTP proxy via sandbox.network.httpProxyPort - works but requires running and maintaining external proxy infrastructure for a setting that should exist natively. Doesn't help for non-HTTP traffic (?)
  3. Drop WebFetch permissions and accept per-use prompts - defeats the convenience of pre-approving safe doc domains and adds friction.
  4. Use Bash(...) deny rules to block specific mutating commands - listed-deny, not default-deny: anything not enumerated is allowed.
  5. Don't add the github.com domain to the WebFetch allowlist. Subdomains like docs.github.com can be added. This works, but requires enumerating every domain you may not want to send arbitrary API requests to, and constantly ensure you never add them to the WebFetch allowlist.
  6. Allow disjoint allow/deny based on HTTP verb (e.g. allow GET towards github.com, but not POST)

Priority

Medium - Would be very helpful

Feature Category

Configuration and settings

Use Case Example

  1. I give claude code a task to fix in my git repo. I'm using the built in sandboxing to reduce the risk of destructive actions on my computer or on the upstream for the repo.
  2. Claude fetches various docs sites (possibly including content under github.com) without my approval due to my WebFetch allow settings
  3. Claude can download packages and run tests due to my sandbox allowlist for the package manager domain.
  4. I can be confident that Claude cannot push changes to github, create PRs, open issues, etc.
  5. "Readonly"/"Safe" git/gh commands can be explicitly allowed (e.g. gh pr search, git fetch)

Additional Context

  • Predecessor request: #31296 - closed by github-actions[bot] as stale, not resolved on merits. Same ask, different framing (filed as bug).
  • Bidirectional symptom: #38735 - WebFetch(domain:X) in permissions.deny punches through and blocks git push and other unrelated network in the sandbox. Same underlying coupling, opposite direction.
  • Related enforcement bugs: #37970, #40213, #29602 - all in the "allowedDomains is not behaving as a strict allowlist" cluster.
  • Docs reference: Sandboxing - Network Isolation
  • Security framing: "permission to read content" != "permission to make network calls from arbitrary subprocesses" is a standard distinction in container/sandbox tooling. WebFetch is observable and reviewed; arbitrary Bash network is not.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗