Egress proxy

Let agents install packages without giving them the internet.

The workspace network has no route out. Everything except the broker and model gateway goes through egress-proxy, the only service on both the workspace and upstream networks. Compose sets HTTPS_PROXY/HTTP_PROXY and points workspace DNS at 127.0.0.1, so external names don't resolve.

Allowlist

{
  "allow": ["registry.npmjs.org:443", "*.pythonhosted.org:443"],
  "deny": ["uploads.example.com"],
  "maxBytesPerHost": 2147483648
}

Point AGENTGATE_EGRESS_CONFIG_PATH at your own copy.

  • Only CONNECT host:port. Any other method gets 405 — no plaintext proxying.
  • Entries are host:port or *.suffix:port. *.example.org does not match example.org.
  • IP literals and invalid entries are rejected at startup.

Always denied

GitHub — github.com, *.github.com, *.githubusercontent.com, *.githubassets.com, *.github.io, ghcr.io — is denied whatever the allowlist says. GitHub access goes through the broker only.

SSRF protection

The proxy resolves every address itself and refuses the tunnel if any is loopback, private, link-local, CGNAT, documentation, multicast, reserved, IPv4-mapped, or a NAT64/6to4 form of those. It connects only to vetted addresses and never re-resolves, so DNS rebinding doesn't work.

Quotas

  • maxBytesPerHost (default 2 GiB) caps bytes in both directions per client and rule.
  • Idle tunnels close after 5 minutes; at most 32 tunnels per client.
  • CONNECT headers must arrive within 10 seconds.

Each decision is logged with host, port, decision, reason, and byte counts — never payloads.

Warning

Allowlisted hosts that accept uploads (like package publish endpoints) remain an exfiltration channel.