Skip to content

Commit 3e7bc53

Browse files
dvdksnclaude
andauthored
Clarify sandbox networking, env sourcing, and approval defaults (#24745)
## Summary - Clarify that `/etc/sandbox-persistent.sh` is sourced when bash runs inside the sandbox, but not when `sbx exec <name> <command>` runs a command directly without a shell. Add a `bash -c` workaround. (Related: docker/sbx-releases#53) - Add FAQ entry explaining why agents run without approval prompts (the sandbox is the safety boundary) and how to re-enable them: change the permission mode inside the session, or build a custom template. (Related: docker/sbx-releases#47) - Add a note to the network policy page and a troubleshooting entry making it explicit that SSH and other non-HTTP protocols are always blocked, regardless of allow rules. (Related: docker/sbx-releases#46) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b266800 commit 3e7bc53

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

content/manuals/ai/sandboxes/faq.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,38 @@ sandbox instead of on your host.
6565
> the sandbox. The agent process can read it directly. Only use this for
6666
> credentials where proxy-based injection isn't available.
6767
68+
Variables in `/etc/sandbox-persistent.sh` are sourced automatically when
69+
bash runs inside the sandbox, including interactive sessions and agents
70+
started with `sbx run`. If you run a command directly with
71+
`sbx exec <name> <command>`, the command runs without a shell, so the
72+
persistent environment file is not sourced. Wrap the command in `bash -c`
73+
to load the environment:
74+
75+
```console
76+
$ sbx exec <sandbox-name> bash -c "your-command"
77+
```
78+
6879
To verify the variable is set, open a shell in the sandbox:
6980

7081
```console
7182
$ sbx exec -it <sandbox-name> bash
7283
$ echo $BRAVE_API_KEY
7384
```
7485

86+
## Why do agents run without approval prompts?
87+
88+
The sandbox itself is the safety boundary. Because agents run inside an
89+
isolated microVM with [network policies](security/policy.md),
90+
[credential isolation](security/credentials.md), and no access to your host
91+
system outside the workspace, the usual reasons for approval prompts (preventing
92+
destructive commands, network access, file modifications) are handled by the
93+
sandbox isolation layers instead.
94+
95+
If you prefer to re-enable approval prompts, change the permission mode
96+
inside the session. Most agents let you switch permission modes after
97+
startup. In Claude Code, use the `/permissions` command to change the mode
98+
interactively.
99+
75100
## How do I know if my agent is running in a sandbox?
76101

77102
Ask the agent. The agent can see whether or not it's running inside a sandbox.

content/manuals/ai/sandboxes/security/policy.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ to all sandboxes on the machine.
1717
The only way traffic can leave a sandbox is through an HTTP/HTTPS proxy on
1818
your host, which enforces access rules on every outbound request.
1919

20+
Non-HTTP TCP traffic, including SSH, can be allowed by adding a policy rule
21+
for the destination IP address and port (for example,
22+
`sbx policy allow network "10.1.2.3:22"`). UDP and ICMP traffic is blocked
23+
at the network layer and can't be unblocked with policy rules.
24+
2025
### Initial policy selection
2126

2227
On first start, and after running `sbx policy reset`, the daemon prompts you to
@@ -171,11 +176,11 @@ my-sandbox network registry.npmjs.org transparent policykit 10:15:20 29
171176

172177
The **PROXY** column shows how the request left the sandbox:
173178

174-
| Value | Description |
175-
| ------------- | --------------------------------------------------------------------------------------------------- |
176-
| `forward` | Routed through the forward proxy. Supports [credential injection](credentials.md). |
177-
| `transparent` | Intercepted by the transparent proxy. Policy is enforced but credential injection is not available. |
178-
| `network` | Non-HTTP traffic (raw TCP, UDP, ICMP). Always blocked. |
179+
| Value | Description |
180+
| ------------- | -------------------------------------------------------------------------------------------------------------- |
181+
| `forward` | Routed through the forward proxy. Supports [credential injection](credentials.md). |
182+
| `transparent` | Intercepted by the transparent proxy. Policy is enforced but credential injection is not available. |
183+
| `network` | Non-HTTP traffic (raw TCP, UDP, ICMP). TCP can be allowed with a policy rule; UDP and ICMP are always blocked. |
179184

180185
Filter by sandbox name by passing it as an argument:
181186

content/manuals/ai/sandboxes/troubleshooting.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,30 @@ To allow all outbound traffic instead:
5151
$ sbx policy allow network "**"
5252
```
5353

54+
## SSH and other non-HTTP connections fail
55+
56+
Non-HTTP TCP connections like SSH can be allowed by adding a policy rule for
57+
the destination IP address and port. For example, to allow SSH to a specific
58+
host:
59+
60+
```console
61+
$ sbx policy allow network "10.1.2.3:22"
62+
```
63+
64+
Hostname-based rules (for example, `myhost:22`) don't work for non-HTTP
65+
connections because the proxy can't resolve the hostname to an IP address in
66+
this context. Use the IP address directly.
67+
68+
UDP and ICMP traffic is blocked at the network layer and can't be unblocked
69+
with policy rules.
70+
71+
For Git operations over SSH, you can either add an allow rule for the Git
72+
server's IP address or use HTTPS URLs instead:
73+
74+
```console
75+
$ git clone https://github.com/owner/repo.git
76+
```
77+
5478
## Can't reach a service running on the host
5579

5680
If a request to `127.0.0.1` or a local network IP returns "connection refused"

0 commit comments

Comments
 (0)