An agent sandbox is supposed to be dangerous in a small, contained way. Give it a repository, a shell, and permission to run generated code; then let it ask a model for help. The awkward part is that its one legitimate outbound request—to an AI API—looks exactly like the first step of a credential-exfiltration or lateral-movement attempt.
Kubernetes has historically made that distinction easy to blur. A Pod that can resolve public DNS can often call the public internet unless an operator has already built and enforced an egress boundary. An ExternalName Service can make a hostname look like a Kubernetes backend, but it does not turn the hostname into a reviewed security decision.
Gateway API 1.6's experimental XBackend gives that decision a first-class shape: an external FQDN, port, protocol, and TLS expectation can live in a named resource rather than in an ad hoc Service or application environment variable. That is useful. It is also not an egress policy. The distinction matters most for a future E2B-style sandbox running arbitrary code on a Cluster-API fleet.
Here is the core model before looking at YAML:
| Layer | Job | What it proves | What it does not prove |
|---|---|---|---|
| Destination declaration | XBackend names api.openai.com:443 and its TLS expectations | The platform has a reviewable record of the intended upstream | That a sandbox cannot open a socket to another host |
| Traffic steering | An egress gateway or proxy sends an approved request to that backend | Approved requests have a controlled path | That every Pod uses that path |
| Network enforcement | Default-deny egress and an FQDN-capable policy allow only DNS plus the approved destination | A sandbox cannot directly reach arbitrary destinations | That a hostname change was approved or credentials are safe |
| Authorization and audit | Admission rules, scoped credentials, and logs govern who can create or use the destination | The exception has an owner and evidence | That untrusted code deserves a broadly privileged API key |
The practical takeaway is deliberately plain: use XBackend to make an allowed AI endpoint legible; use independent controls to make every other endpoint unavailable. Treat either half as optional and the design collapses.
The concrete case: one sandbox, one named API destination
The Gateway API 1.6 reference introduces XBackend in the experimental channel for external hostnames. The resource has a narrow job: define where a Gateway, acting as a client, should connect and how it should do so. Its ExternalHostname type replaces the common workaround of a synthetic ExternalName Service.
For an agent-sandbox namespace, the reviewed declaration can be as small as this:
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: XBackend
metadata:
name: openai-api
namespace: agent-sandboxes
labels:
platform.bex.co/egress-class: model-api
spec:
type: ExternalHostname
port:
port: 443
externalHostname:
hostname: api.openai.com
protocol: HTTP
tls:
mode: ServerOnly
validation:
hostname: api.openai.comAn HTTPRoute can then refer to that destination from a Gateway which the chosen controller has configured as an egress proxy:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: sandbox-model-proxy
namespace: agent-sandboxes
spec:
parentRefs:
- name: sandbox-egress-gateway
rules:
- backendRefs:
- group: gateway.networking.x-k8s.io
kind: XBackend
name: openai-api
port: 443This is intentionally a minimal representation, not a copy-paste sandbox product. In particular, Gateway API does not magically intercept a Pod's ordinary TLS connection just because the route exists. The platform must decide how requests enter the trusted gateway: an internal model proxy is often the cleanest choice, while an explicit HTTP proxy or a controller-specific egress Gateway may fit another deployment. The controller must support the experimental resource, and its status must show that the parent accepted and programmed the backend. A manifest accepted by the API server alone is not evidence that traffic will flow.
The TLS fields are not decorative. ServerOnly means the connection validates the upstream server certificate; the hostname makes the expected identity explicit. The specification says external-hostname backends should use TLS and treats an unencrypted external connection as a security risk. When a model provider offers a private endpoint or requires client authentication, the same boundary is where a platform should set the more restrictive connection expectations—not leave those choices hidden in sandbox code.
This produces a concrete review question. Instead of asking, “Why does this Pod have unrestricted internet access?”, a reviewer can ask, “Why is openai-api allowed, which sandbox class may reference it, and which human or service owns that exception?” That is a substantial improvement in platform vocabulary. It is not yet containment.
What still has to deny the rest of the internet
An arbitrary-code sandbox needs a deny-by-default posture. Kubernetes documents that Pods are non-isolated for egress by default; creating a NetworkPolicy has no effect unless the cluster network plugin enforces it. A default-deny policy also blocks DNS, so DNS needs its own deliberately narrow exception. Those operational facts are why an egress design needs more than a Gateway object.
The complete control map for the example looks like this:
| Control | Implementation intent | Failure it closes |
|---|---|---|
| Namespace default deny | Select every sandbox Pod with an Egress NetworkPolicy that has no destinations | A newly created sandbox gets public internet by accident |
| DNS exception | Allow only the cluster resolver on its required UDP/TCP port | The default-deny policy breaks resolution, prompting someone to reopen all egress |
| FQDN enforcement | Use an enforcement-capable CNI or egress gateway policy that permits the resolved addresses for api.openai.com:443 only | A sandbox bypasses the proxy and opens a direct connection to an arbitrary IP |
| Gateway-only path | Limit sandbox-to-network traffic to the approved proxy/Gateway identity where the design requires mediation | A well-defined route exists, but the Pod simply goes around it |
| Admission ownership | Restrict creation and modification of XBackend, routes, and any FQDN-policy CRDs to a platform-controlled service account | A tenant creates payments.example or an internal-looking destination as its own exception |
| Credential boundary | Put the provider credential in a model proxy, or mint short-lived credentials with a narrow scope and budget | Generated code reads a reusable, broadly privileged API key |
| Evidence | Log destination, requesting sandbox/workload identity, policy decision, and bytes or requests; alert on denied attempts | The team cannot distinguish an expected tool call from an attempted escape |
The FQDN row is the one most often hand-waved. Standard Kubernetes NetworkPolicy operates on Pod, namespace, and IP/CIDR selectors. A model provider's addresses are not a stable hand-maintained CIDR allowlist. An implementation such as a CNI with DNS-aware egress policy can map an approved name to current addresses, but that capability is not supplied by XBackend or by the base NetworkPolicy API. It needs to be selected, configured, and tested as an enforcement plane of its own.
That separation also makes DNS rebinding easier to reason about. Gateway API calls out the history of ExternalName DNS-rebinding concerns, including CVE-2021-25740, and ExternalHostname rejects names ending in .cluster.local. That validation removes one confusing class of target; it does not make DNS universally trustworthy. A serious implementation still limits who may declare names, observes resolution changes, and makes the dataplane enforce the intended name-to-address policy rather than trusting a one-time lookup.
There is one more uncomfortable constraint: a sandbox that talks directly to a model API must possess a credential or a way to obtain one. A model proxy gives the platform a different security posture. The sandbox presents its own workload identity to the proxy; the proxy applies model, token, request-rate, and destination policy; and only the proxy handles the provider secret. XBackend still makes the proxy's external destination reviewable, but it is not being asked to solve secret distribution.
A rollout that produces evidence, not only manifests
On a Cluster-API fleet, make this a staged platform capability rather than a namespace-level YAML experiment. The following five-step runbook is intentionally testable.
-
Establish the baseline. Create the sandbox namespace with default-deny egress and the minimum resolver exception. Start a disposable sandbox and record that a request to both
api.openai.comand an unrelated public host fails. This confirms the negative condition before creating an exception. -
Check the implementation, not just the CRD. Install the appropriate Gateway API experimental bundle only after verifying the controller's documented
XBackendsupport. Create the named backend and route, then inspect the controller's ancestor conditions for acceptance and programming. Do not declare success merely becausekubectl applyreturned zero. -
Add one enforceable exception. Configure the CNI or egress dataplane's FQDN policy for
api.openai.com:443, plus the route or model-proxy path. Prove three outcomes from the sandbox: the approved request succeeds, a request to another hostname fails, and a direct connection to an unrelated IP fails. A test that checks only the successful model call proves convenience, not containment. -
Exercise change and failure paths. Rotate the sandbox's credential or proxy identity, remove the backend reference, and confirm that new calls fail closed. Observe what happens when the approved hostname resolves to a changed address, when DNS is unavailable, and when the upstream certificate does not validate. These are the cases in which an “allowlist” quietly turns into “allow anything so the demo works.”
-
Make the exception operable. Require an owner, expiry or review date, and a change record for each external backend. Export gateway, DNS-policy, and proxy logs to the fleet's normal observability stack. During an incident, the operator should be able to answer: which sandbox contacted which hostname, through which route, with which policy revision, and whether the request was accepted or denied.
Cluster API helps with the infrastructure half of this work: the node image, CNI, Gateway controller, resolver behavior, and policy enforcement expectations can be versioned as a fleet contract rather than improvised on each server. It does not make the egress policy safe by itself. The durable asset is a repeatable node and workload baseline with negative tests in CI and after every controller or CNI upgrade.
Use the shape now; do not bet production isolation on it yet
XBackend is currently an experimental-channel API, not a portability guarantee. Gateway API's own versioning policy is explicit: experimental resources can change or be removed, and the project recommends the standard channel for stable use. Controller implementations can also differ in which experimental features they support. Treat an XBackend manifest as an evaluated design pattern until the resource, conformance coverage, and controller support have earned a stronger production commitment.
That does not mean waiting to design secure egress. The portable pieces are available today:
- default-deny egress plus only the DNS and in-cluster dependencies a sandbox needs;
- a vetted egress Gateway or model proxy that owns outbound credentials;
- a network dataplane with enforceable FQDN policy where external names are necessary;
- admission restrictions and audit records around every exception; and
- tests that demonstrate both the allowed request and the denied escape.
The experimental resource improves the first of those pieces: it turns an external destination into a named object that policies, routes, status, and reviews can reference. That is exactly the useful direction for agent infrastructure—make intent machine-readable before asking an agent to operate it. But the safe promise to a user is not “the route exists.” It is “this sandbox can reach this one service, and we can prove what stops it reaching the rest.”
Bex.co is the open-source, AI-native Render alternative—push a Git repo and get a running HTTPS service on machines you own. Its Cluster-API direction is a natural place to make fleet and workload policy explicit rather than hiding it in one-off server setup. Star the project on GitHub or explore self-hosted app operations at Bex.co.
Sources
- Gateway API: Backend and ExternalHostname reference
- Gateway API v1.6 API reference: XBackend and backend TLS
- Gateway API versioning and experimental-channel guarantees
- Kubernetes: NetworkPolicy egress behavior and default-deny example
- Kubernetes security advisory: CVE-2021-25740
- Cilium: DNS-based FQDN egress policy
- E2B sandbox documentation



