anthropics / anthropics/claude-code

[FEATURE] Sandbox network: let the user decide on hosts outside the allowlist in auto mode, instead of the classifier

Open
#94,306 0 comments 0 reactions 0 assignees View on GitHub
area:permissions area:sandbox area:security enhancement
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist

- [x] I have searched [existing requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)

### Problem Statement

The Bash sandbox has an allowlist, `sandbox.network.allowedDomains`. When a sandboxed command reaches a host outside the list, Claude Code shows this prompt in Manual mode:

```
Network request outside of sandbox
Host: www.google.com
Do you want to allow this connection?
```

In auto mode, the same command with the same settings shows no prompt. The classifier answers instead, and the request usually succeeds. The documentation describes this: "The first time a command needs a new domain, Claude Code prompts for approval, or in auto mode sends the request to the classifier."

There is no way to get the prompt back in auto mode. The only setting that acts on this decision is `sandbox.network.strictAllowlist: true`, and it does not meet the need. It replaces the prompt with a denial, so there is no decision left to take at run time. The list of accepted domains has to be frozen in advance, in the configuration of a project or of an environment. A host that a session needs once means a settings edit. The setting is also honored only from user or managed settings (#90355).

The result is a gap between the documentation and the product. The sandboxing page says: "Domain restrictions: Claude Code pre-allows no domains by default." The permission modes page says: "On Pro, Max, and Team plans, the built-in starting permission mode is auto mode." In the default mode, the effective allowlist is the classifier's judgement of the current command.

### The classifier decides on the host without the context that carries the risk

This is a security problem on its own, and it does not depend on the quality of the model. The decision reaches the classifier when the command opens the connection. Its input is the host, the port, and the command that runs. What the request carries is not part of that input. A whole class of decisions is therefore impossible to take correctly:

- **A host is not a permission.** For example, `github.com` serves a clone of a public repository. The same host also accepts a push of the working tree to a new remote. The classifier answers one question: may this command reach this host. The risk is in the direction of the data and in the content of the request.
- **The command line often names neither the host nor the action.** For example, a sandboxed command can be `./gradlew build` and it contains no URL. The connection still reaches the classifier, with a host, a port, and a command whose network behavior stays invisible.
- **An exfiltration channel can use a trusted host.** The classifier may receive the instruction to allow a trusted domain (e.g., the host of the git remote), the traffic looks ordinary, and the data leaves the machine.
- **The user holds the context that the classifier does not receive.** The user knows the task. A host that the task does not need is visible to them in one line.

The conclusion is not that the classifier answers badly. It is that the answer needs information that the question does not contain.

### The documented human checkpoint does not cover the network decision

The auto mode configuration page names one mechanism for this need, under [Add a human checkpoint](https://code.claude.com/docs/en/auto-mode-config#add-a-human-checkpoint):

> The most direct mechanism is `permissions.ask`. Content-scoped ask rules like the ones below are evaluated before the classifier and always force a permission prompt, even in auto mode, because an explicit ask rule is your stated intent to be prompted for that action.

No equivalent rule exists for the network boundary. So the network boundary is the only sandbox boundary that auto mode leaves with no human checkpoint.

### Proposed Solution

Make `sandbox.network.strictAllowlist` accept a third value, `"ask"`. This mirrors `sandbox.allowUnsandboxedCommands`, which already accepts `true | false | "ask"` for the other sandbox boundary.

```json
"sandbox": {
"network": {
"allowedDomains": ["*.example.com"],
"strictAllowlist": "ask"
}
}
```

- `false`: current behavior. Prompt in Manual mode, classifier in auto mode.
- `true`: current behavior. Deny.
- `"ask"`: always show the "Network request outside of sandbox" prompt to the user for a host outside the allowlist, in every mode that can prompt, auto mode included. Deny in `dontAsk` mode and in a `-p` run without `--permission-prompt-tool`, the same way other ask-level decisions behave there.

In `"ask"` mode, the allowlist itself must keep working as it does today:

- The allowlist stays the merged list from every settings scope: `sandbox.network.allowedDomains` from user, project and local settings, plus `WebFetch(domain:...)` allow rules. A project can add the domains it needs in its own `.claude/settings.json`, and those hosts never prompt. Only a host outside the merged list prompts.
- "Yes, and don't ask again" keeps saving an `allowedDomains` entry to local settings, so the answer persists across sessions.
- `allowManagedDomainsOnly` keeps its meaning: when it is set, only the managed entries count, and a project cannot widen the list.

### Alternative Solutions

- `strictAllowlist: true` in user settings. This is what we run today. It is a hard deny with no prompt. The accepted domains have to be listed in advance in the project or environment configuration, and every new host means editing a settings file. The one-shot "Yes" and "Yes, and don't ask again" answers of the prompt are lost.
- An ask rule on the command, as the [Add a human checkpoint](https://code.claude.com/docs/en/auto-mode-config#add-a-human-checkpoint) recipe does for `git push`. This cannot work for a network access. The rule matches the command text, and the command that opens the connection is a script, a build task or a compiled binary. The checkpoint page states the same limit for its own recipe: "A push Claude writes another way, such as `git -C push` or `git -c = push`, doesn't match the rule, so it isn't checkpointed."
- An ask rule on `WebFetch(domain:...)`, the only rule form that names a host. This does not work for a sandboxed command. Claude Code prompts when Claude uses the WebFetch tool. It does not prompt when a sandboxed Bash command connects to the same host, and the connection proceeds.

### Priority

High - Significant impact on productivity

### Feature Category

Configuration and settings

### Use Case Example

1. An administrator sets `allowedDomains` to the company's internal zone and its package registries in user or managed settings, and sets `strictAllowlist` to `"ask"`.
2. A project adds the domains it needs, for example its own artifact server, to `allowedDomains` in its `.claude/settings.json`. Claude reaches them without a prompt.
3. A developer works in auto mode. Claude runs `curl https://api.github.com/...` from a Bash command.
4. Claude Code shows the "Network request outside of sandbox" prompt with the host. The developer answers Yes, No, or "Yes, and don't ask again".

### Additional Context

_No response_

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing the handling of sandbox.network.strictAllowlist and compare it with sandbox.allowUnsandboxedCommands, which already supports an ask value. Check how allowedDomains are merged and how network permission decisions behave across manual, auto, dontAsk, and -p modes. Done means an ask value prompts for hosts outside the merged allowlist and preserves the documented allow, deny, and remember behaviors.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.