Skip to content

agent: Model sandbox network escalation as a host allowlist - #59219

Merged
MartinYe1234 merged 7 commits into
mainfrom
http-proxy-03-agent-model
Jun 15, 2026
Merged

agent: Model sandbox network escalation as a host allowlist#59219
MartinYe1234 merged 7 commits into
mainfrom
http-proxy-03-agent-model

Conversation

@rtfeldman

Copy link
Copy Markdown
Contributor

Third of a four-PR stack adding hostname-allowlisted network access to agent terminal sandboxing. Stacked on #59218 — review/merge #59217 and #59218 first.

Replaces the boolean allow_network terminal-sandbox escalation with a hostname allowlist. The terminal tool now takes allow_hosts (exact hostnames or leading-*. subdomain wildcards, validated up front) and allow_all_hosts as a broad escape hatch. Approval prompts name the requested hosts, thread grants and persistent "allow always" settings cover requests via host-pattern subsumption the same way write paths use subtree containment, and the authorization card in the agent panel lists the requested hosts.

Host allowlists aren't enforced yet in this PR: SandboxWrap carries the allowlist, but any network request still maps to unrestricted egress at the Seatbelt layer, matching previous behavior. Enforcement via the in-process proxy lands in the final PR of the stack. All of this is behind the existing sandboxing feature flag. For non-local projects (where the loopback proxy won't apply), host requests are widened to "arbitrary network access" before prompting so approvals match enforcement. Old persisted network: bool authorization details still deserialize via a serde alias.

Release Notes:

  • N/A

@rtfeldman rtfeldman self-assigned this Jun 12, 2026
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jun 12, 2026
@zed-community-bot zed-community-bot Bot added the staff Pull requests authored by a current member of Zed staff label Jun 12, 2026
@rtfeldman
rtfeldman force-pushed the http-proxy-03-agent-model branch from 1ab33c3 to b47c0ae Compare June 12, 2026 19:59
@rtfeldman
rtfeldman force-pushed the http-proxy-02-sandbox-enum branch from 70035ec to 683e314 Compare June 12, 2026 19:59
First of a stack adding hostname-allowlisted network access to agent
terminal sandboxing. This PR adds a new `http_proxy` crate containing only
the allowlist policy types: `HostPattern` (exact hostnames or leading-`*.`
subdomain wildcards, with IDN-to-punycode normalization and IP-literal /
localhost rejection) and `Allowlist`, plus host-pattern subsumption
(`covers`) used later to decide when an already-granted permission covers a
new request.

Pure, self-contained logic with no callers yet; the upstream-proxy config
and the proxy server that enforces these policies land in later PRs.

Release Notes:

- N/A
Second of the stack. Adds `UpstreamProxy`: parsing of an upstream HTTP
proxy from the environment (`HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` and
lowercase forms) with `NO_PROXY` bypass matching delegated to the
`proxyvars` crate, basic-auth credentials (kept out of `Debug`/`Display`),
and IPv6/default-port normalization. Used by the proxy server in the next
PR to chain outbound connections through a corporate proxy when one is
configured.

Release Notes:

- N/A
Final piece of the crate: the in-process HTTP/HTTPS proxy server that
enforces an `Allowlist`. It speaks HTTP CONNECT for HTTPS tunnels and
forward proxying for plain HTTP, vets resolved addresses against
loopback/private/link-local ranges to prevent DNS-rebinding past the
sandbox, pins each connection to the destination approved for its first
request (so later keep-alive requests can't escape the policy decision),
optionally chains through the `UpstreamProxy`, and bounds header sizes,
connection counts, and connect/handshake waits since its sole client is
untrusted model-driven code running inside the editor process. Includes
end-to-end tests covering allowed/denied CONNECT and HTTP forward,
IP-literal handling, DNS-rebinding denial, and upstream chaining.

Still has no callers; wired into the agent terminal sandbox in later PRs.

Release Notes:

- N/A
Replace the `allow_network: bool` field on the Seatbelt `SandboxPermissions`
with a `NetworkAccess` enum: `None` (block all egress), `All` (the previous
`allow_network: true` behavior), and `LocalhostPort(u16)`, which confines a
sandboxed command to a single loopback port. The new variant emits a
Seatbelt rule permitting outbound TCP only to `localhost:<port>` and isn't
used yet; it exists to pin sandboxed commands to the in-process network
proxy in a later commit.

The sole consumer, `acp_thread`'s terminal wrap, maps its existing boolean
to `All`/`None`, so behavior is unchanged.

Release Notes:

- N/A
Replace the boolean `allow_network` terminal-sandbox escalation with a
hostname allowlist. The `terminal` tool now takes `allow_hosts` (exact
hostnames or leading-`*.` subdomain wildcards, validated up front via
`http_proxy::HostPattern`) and `allow_all_hosts` as a broad escape hatch.
Approval prompts name the requested hosts, thread grants and persistent
"allow always" settings (`network_hosts` / `allow_all_hosts`, replacing
`allow_network`) cover requests via host-pattern subsumption the same way
write paths use subtree containment, and the authorization card in the
agent panel lists the requested hosts in a collapsible section.

Host allowlists aren't enforced yet: `SandboxWrap` carries the allowlist,
but any network request still maps to unrestricted egress at the Seatbelt
layer, matching previous behavior. Enforcement via an in-process proxy
lands in the next commit. For non-local projects (where that proxy won't
apply), host requests are widened to "arbitrary network access" before
prompting so approvals match enforcement.

Old persisted `network: bool` authorization details still deserialize via
a serde alias.

Release Notes:

- N/A
@rtfeldman
rtfeldman force-pushed the http-proxy-03-agent-model branch from b47c0ae to ee98620 Compare June 13, 2026 02:22
@rtfeldman
rtfeldman force-pushed the http-proxy-02-sandbox-enum branch from 683e314 to 9e31735 Compare June 13, 2026 02:22
@rtfeldman
rtfeldman marked this pull request as ready for review June 15, 2026 18:48
Base automatically changed from http-proxy-02-sandbox-enum to main June 15, 2026 21:25
@MartinYe1234
MartinYe1234 enabled auto-merge June 15, 2026 21:34
@MartinYe1234
MartinYe1234 force-pushed the http-proxy-03-agent-model branch from 0b80817 to ee98620 Compare June 15, 2026 21:44
@MartinYe1234
MartinYe1234 added this pull request to the merge queue Jun 15, 2026
Merged via the queue into main with commit 8117571 Jun 15, 2026
32 checks passed
@MartinYe1234
MartinYe1234 deleted the http-proxy-03-agent-model branch June 15, 2026 22:09
This was referenced Jun 18, 2026
jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
…stries#59219)

Third of a four-PR stack adding hostname-allowlisted network access to
agent terminal sandboxing. Stacked on zed-industries#59218 — review/merge zed-industries#59217 and
zed-industries#59218 first.

Replaces the boolean `allow_network` terminal-sandbox escalation with a
hostname allowlist. The `terminal` tool now takes `allow_hosts` (exact
hostnames or leading-`*.` subdomain wildcards, validated up front) and
`allow_all_hosts` as a broad escape hatch. Approval prompts name the
requested hosts, thread grants and persistent "allow always" settings
cover requests via host-pattern subsumption the same way write paths use
subtree containment, and the authorization card in the agent panel lists
the requested hosts.

Host allowlists aren't enforced yet in this PR: `SandboxWrap` carries
the allowlist, but any network request still maps to unrestricted egress
at the Seatbelt layer, matching previous behavior. Enforcement via the
in-process proxy lands in the final PR of the stack. All of this is
behind the existing sandboxing feature flag. For non-local projects
(where the loopback proxy won't apply), host requests are widened to
"arbitrary network access" before prompting so approvals match
enforcement. Old persisted `network: bool` authorization details still
deserialize via a serde alias.

Release Notes:

- N/A

---------

Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Co-authored-by: Martin Ye <martin@zed.dev>
jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
…d-industries#59220)

Final PR of a four-PR stack adding hostname-allowlisted network access
to agent terminal sandboxing. Stacked on zed-industries#59219 — review/merge zed-industries#59217,
zed-industries#59218, and zed-industries#59219 first.

Spawns the `http_proxy` allowlisting proxy for sandboxed terminal
commands that request network, and pins the Seatbelt policy to its
loopback port (`NetworkAccess::LocalhostPort`) so all egress is forced
through it. The child's proxy environment variables are pointed at the
proxy and any inherited `NO_PROXY` is blanked so nothing connects
direct; a real upstream proxy from the environment is chained through
when present. The proxy and its Seatbelt config file share one RAII
handle so both live exactly as long as the command, and per-connection
events are drained to the log.

The proxy binds loopback, so it only applies to local projects on macOS;
elsewhere the wrap falls back to unrestricted egress as before (the
agent layer widens such requests accordingly).

Release Notes:

- Added the ability to grant agent terminal commands network access to
specific hosts (rather than all-or-nothing), enforced by an allowlisting
proxy.

---------

Co-authored-by: Martin Ye <martin@zed.dev>
Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement staff Pull requests authored by a current member of Zed staff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants