Network and egress
How DefenseClaw's egress proxy decides every site a sandboxed agent contacts, the open, balanced and strict network profiles, the blocklist, unblocks, asks, large-upload alerts and what the agent is told when it is blocked.
A sandbox has no network of its own. It has three ways out, and DefenseClaw watches all three:
- Web traffic goes through DefenseClaw's egress proxy, which the
sandbox reaches at
host.openshell.internalthroughHTTPS_PROXYandHTTP_PROXY. The proxy decides and logs every site. - Model calls go to the harness's model provider directly through OpenShell, which adds the real credential outside the sandbox. The sandbox only ever holds a placeholder.
- Anything else, such as a client that ignores the proxy settings, is refused by OpenShell, which files a connection request. DefenseClaw decides most of those on its own and asks you about the rest.
How a site is decided
The proxy checks each request in a fixed order, and the first match decides. Every sandbox is decided by its own policy: another sandbox's pack, block list or unblocks never apply to it.
In words:
- This machine, link-local and cloud metadata addresses are always
blocked. Nothing opens them. To let the sandbox use one service on your
machine, start it with
--host-port PORT, which you then approve. - Private networks such as
10.x,192.168.xand intranet names are blocked unless an allow entry names them exactly. - Ports other than those on the proxy port list are blocked. The default list is 80 and 443.
- Your organization's block list, then its allow-only list, if it has one. Nothing you do unblocks these.
- Your block list, the pack's entries plus
openshell.egress.block. An unblock does not lift it; remove the entry instead. - Your unblocks allow the site.
- The allow list allows the site, and exempts it from the blocklist feed.
- The blocklist feed blocks paste sites, anonymous file drops, webhook catchers, tunnels and anonymizers. You can unblock these.
- The profile's default decides everything else.
openallows any host name but blocks a bare IP address until you unblock it, because an IP address would get around the name-based blocklist.balancedblocks anything outside its curated allowlist, and you can unblock it.
How a destination is decided lists all twelve steps, including the organization settings.
Network profiles
Every sandbox runs one policy pack. The built-in packs set the network profile and more:
open (default) | balanced | strict | |
|---|---|---|---|
| Web access | Any site by name, except the blocklist, private networks and this machine | Only a curated developer allowlist: package registries, source hosting, toolchains and documentation | None: only the harness's model provider |
| Banner | network: open + blocklist | network: allowlist (balanced) | network: provider hosts only (strict) |
| Connection requests | Decided automatically | Triaged, the unclear ones asked | Every one asked |
| Large-upload alert | 25 MiB | 10 MiB | 5 MiB |
| Your project | Mounted live | Mounted live | Copied |
| Skip-permissions mode | On | On | Off: the harness keeps its prompts |
Pick one for a run:
defenseclaw sandbox run claude --profile balanced
defenseclaw sandbox run claude --profile strictOr set it for every run with openshell.profile in
~/.defenseclaw/config.yaml. On a Mac every run works on a copy, whichever
pack it uses.
The open profile is a deliberate trade-off
With open, an agent tricked by a prompt injection could send your code to
any site that is not on the blocklist. DefenseClaw's tool-call checks, the
blocklist, large-upload alerts, hidden secrets and endpoint-bound
credentials limit the damage. The proxy sees HTTPS only as encrypted
tunnels, so it cannot tell a download from an upload. For sensitive code,
use balanced or strict.
See policy packs and admin controls to write your own pack or set limits for your organization.
Allow and block your own sites
To let every sandbox reach an intranet host, such as a package mirror, add its exact name or address to the allow list. To keep sandboxes away from a site, add it to the block list:
openshell:
egress:
allow:
- npm.mirror.corp.example
block:
- files.example.netA change reaches running sandboxes on the next config reload.
Unblock a site
When a block is a false positive, lift it for one sandbox or for all of them:
defenseclaw sandbox unblock webhook.site --sandbox myapp-7f3a
defenseclaw sandbox unblock webhook.site --always--always adds the host to openshell.egress.unblocked in config.yaml.
You can also unblock from the TUI (u in the Sandboxes panel) or from the
macOS app's notification, menu bar or Sandboxes view.
An unblock lifts blocklist-feed blocks, IP-address blocks and, with
balanced, sites outside the allowlist. It never opens this machine,
private networks or metadata addresses, and never overrides your block list
or your organization's. If your organization turns unblocking off
(openshell.admin.allow_unblock: false), the command says so:
blocked by your organization's DefenseClaw policy: egress.unblockstrict has no web proxy, so there is nothing to unblock there; its direct
connection requests wait as asks instead.
Asks
A connection that does not go through the proxy is refused by OpenShell,
which files a request to open it. DefenseClaw decides most of those itself.
It asks you only about doors into your machine or network (a port on this
machine, a private address, an intranet name) and about requests OpenShell's
policy advisor flags. balanced also asks about sites outside its
allowlist, and strict about every request.
defenseclaw sandbox approvals --watch
defenseclaw sandbox approve myapp-7f3a ap_5f2c9a1e7b3d4c60
defenseclaw sandbox reject myapp-7f3a ap_5f2c9a1e7b3d4c60approve --always keeps the decision for future sandboxes, except for your
own machine and private networks, which open only for one sandbox at a time.
An approval takes effect at the sandbox's next quiet moment, because every
OpenShell policy change closes its open connections.
Large uploads
The proxy counts what each sandbox sends. When a sandbox sends more than the threshold to a site it had not contacted before, DefenseClaw reports it in the feed and as a finding. The upload itself goes on.
To cut such uploads off, turn the block on:
openshell:
egress:
large_upload_mb: 10
block_large_uploads: trueWith the block on, the upload stops before the chunk that would take it past the threshold, and later connections to that site are refused. The feed shows:
✗ files.example.net (large upload blocked: this sandbox tried to send more than 10 MiB to a destination it had not contacted before) → unblock: defenseclaw sandbox unblock files.example.net --sandbox myapp-7f3aSites you unblocked or put on an allow list are exempt: uploads there are
only reported. The balanced allowlist does not exempt a site, so a first
large push to github.com is cut too. Add such hosts to
openshell.egress.allow before you turn the block on. An organization can
turn the block on for every sandbox with openshell.admin.block_large_uploads.
See large-upload alert threshold.
What the agent is told
A blocked agent should stop and tell you, not look for another way out. DefenseClaw tells it so in two ways.
A plain HTTP request gets a 403 with a JSON body written for the
agent (shortened here):
{
"error": "egress_blocked",
"message": "DefenseClaw blocked sandbox egress to webhook.site:80 (webhook_catcher): Webhook catchers record every request sent to them for whoever holds the URL, a common exfiltration sink.",
"host": "webhook.site",
"port": 80,
"category": "webhook_catcher",
"source": "feed",
"mode": "open",
"sandbox": "myapp-7f3a",
"unblockable": true,
"how_to_unblock": "Tell the user DefenseClaw blocked this destination. They can allow it for this sandbox with `defenseclaw sandbox unblock webhook.site --sandbox myapp-7f3a`, for every sandbox with `defenseclaw sandbox unblock webhook.site --always`, or from the DefenseClaw activity feed. Do not try to reach it another way."
}An HTTPS request fails at the tunnel, so tools show only a connection
error such as curl: (56) CONNECT tunnel failed, response 403. After the
shell or web-fetch tool call, DefenseClaw's hooks add a note to the
harness's context that names the blocked site, why it was blocked and the
unblock command, and tells the agent not to try another way. A cut large
upload is reported the same way.
| Harness | Gets the note from the hooks |
|---|---|
| Claude Code, Codex, GitHub Copilot CLI, Cursor, Devin | Yes |
| Other harnesses | No: the activity feed and your terminal report the block |
Each block is told once, and only to the sandbox that hit it.
The proxy credential in verbose output
The proxy address the sandbox gets holds a user name and password of its
own, so curl -v prints a Proxy-Authorization: Basic … header, and the
agent may warn you that a credential leaked. It is not one of your secrets.
DefenseClaw makes one for each sandbox; it works only on the egress proxy on
this machine's loopback address, lets the sandbox reach only what its policy
allows, and stops working when the sandbox is deleted.
See what happened
defenseclaw sandbox activity -f
defenseclaw sandbox status myapp-7f3a
defenseclaw sandbox policy explainactivity is the live feed of sites, blocks, asks and findings. The
Egress row of status counts the sites contacted and blocked and the
bytes sent and received. policy explain shows each effective setting and
the layer it came from: the pack, your config, a run option or your
organization.
Your first sandboxed session
A guided tour of one DefenseClaw sandbox session, from the launch banner through the activity feed, a blocked site and its unblock, to the end-of-session review and undo or pull.
TUI and macOS app
Watch and manage OpenShell sandboxes from the DefenseClaw terminal UI's Sandboxes panel or the macOS app's Sandboxes view, menu bar and notifications, and run sandbox setup from either.