Skip to content

The net kind

Everything that leaves the machine checks the same gate kind: net. Four tools sit behind it — http_read, http_write, dns_resolve and ping — and the Target they all carry is the host. That is the point: one allowlist of hosts spans HTTP, DNS and ICMP, so allowing api.github.com once does not have to be re-decided per protocol.

At a glance

Kindnet — tools.NetKind
Targetthe host — api.github.com, example.com, an IP for ping
Root policyevery net action asks, read and write alike; you choose how long the yes lasts
Matchertools.HostMatch — exact host, *.domain for a domain and its subdomains, or * for any

Tools

  • http_read read gated — read a URL (GET/HEAD)
  • http_write write gated — send data (POST/PUT/PATCH/DELETE)
  • dns_resolve read gated — resolve a hostname's DNS records
  • ping read gated — one ICMP echo to a host

Grants

When you approve a net action you may remember it. A remembered grant is a {kind, target} pair; RecallAlways grants are written to grants.json in the workspace, session grants live only in memory and die with the process. The target is a host pattern, matched by tools.HostMatch.

{ "kind": "net", "target": "api.github.com" }
{ "kind": "net", "target": "*.github.com" }
{ "kind": "net", "target": "*" }
  • *.github.com covers the domain and its subdomains (github.com, api.github.com); * on its own means any host — the widest grant there is.
  • The approval prompt offers exactly one widening beyond the exact host: the parent domain (api.example.com → *.example.com). A bare example.com offers none.
  • A grant covers the kind, not the tool. Allowing net for api.github.com lets http_read, http_write, dns_resolve and ping reach that host — they share one allowlist by design.
  • Redirects are re-checked: each hop is a fresh gate.Check against the new host, so a redirect cannot smuggle a request to a host you never allowed.

Limits

  • Response body — capped at 64 KiB handed back to the caller; the rest is dropped.
  • Request headers — a guest cannot set them. Authorization, Cookie, Proxy-Authorization and friends are the host's channel; only Content-Type comes from the caller.
  • Methods — http_read accepts GET/HEAD only; a mutating method there is rejected.

Credentials

  • Credentials are attached host-side, at the boundary, for the matching host only. The guest never sees the token and never picks it — the destination does.
  • A request cannot carry its own credential. Headers are not refused but absent — the tools take a URL, a method, a body and a content type, and nothing else reaches the wire. A URL with user:pass@host is refused outright, on the first request and on every redirect hop.

Leak scanning

Bidirectional — a secret can neither be smuggled out nor echoed back:

  • Egress (the request): URL, headers and body are scanned before the host stamps in its own credential — a request carrying a stored vault secret is blocked.
  • Ingress (the response): body and header values are scanned and any echoed secret is redacted before the model sees it.
  • Stripped outright: credential-bearing response headers — Set-Cookie, Set-Cookie2, Authorization, WWW-Authenticate, Proxy-Authenticate (the guest has no cookie jar).

Why DNS and ping gate at all

Neither sends payload anywhere, so at first glance both look free. They are gated because a hostname is a channel: a lookup of secret-value.attacker.example exfiltrates that value in the query itself, and the answer is irrelevant. Timing a ping sweep maps an internal network just as well. Both carry the same Target as HTTP — the host — so one decision covers the reach, whichever protocol asks for it.

What ping needs from the OS

ping sends one ICMP echo. On a host that does not permit unprivileged ICMP sockets the call fails at the OS, not at the gate — a denial you see as an error, after the approval, not instead of it.