Network Egress Allowlists for Coding Agent Sandboxes

A coding agent is most useful when it can fetch source, install dependencies, call an approved model gateway, and run checks. Those same capabilities can expose repository contents or build credentials when a tool, dependency, or prompt is untrusted. A network egress allowlist turns that broad capability into a small, reviewable contract: these destinations, ports, and purposes are allowed for this run; everything else is denied.

This is a practical operating guide, not a claim that one firewall rule makes an agent safe. The control should sit beside repository permissions, sandbox isolation, dependency review, and human approval. The NIST SP 800-207 zero-trust architecture is a useful design anchor because it rejects implicit trust based on network location or ownership and puts authorization before a resource session. Apply that idea to every outbound connection made by an agent.

Last reviewed: 2026-08-09

Direct answer

Start with a default-deny policy at the sandbox boundary. Give each destination a named purpose, an exact transport and port, and an owner. Route permitted traffic through a controlled proxy or service gateway when possible. Make DNS resolution part of the policy, and test direct-IP and IPv6 paths so a hostname rule cannot be bypassed. Record every allow and deny decision with metadata that cannot reveal source, prompts, headers, or credentials.

A useful policy has five layers:

  1. Inventory. List the services the task actually needs: source control, an internal package mirror, a model gateway, test fixtures, and observability endpoints. Separate build-time needs from runtime needs. A destination without a purpose is not ready for the allowlist.
  2. Isolation. Launch the agent in a network namespace, container, or pod with no implicit route to the host or a broad corporate network. The Docker networking overview notes that containers have outgoing connectivity by default on the default bridge, while the none driver completely isolates a container from the host and other containers. Treat the default bridge as a starting point to review, not as an egress policy.
  3. Authorization. Permit only the destination identity and port needed for the purpose. A rule for port 443 alone is not a rule for a trusted service; it is merely a transport permission. Prefer a proxy that resolves and authorizes the destination, or an enforcement point that can inspect the resolved address and deny unapproved routes.
  4. Verification. Run an allow test and a deny test for every rule. Confirm that the request used the intended proxy or network, that a denied request cannot fall back to a direct route, and that the policy revision seen by the sandbox matches the reviewed revision.
  5. Evidence. Keep a small record for each connection attempt. Store the run identifier, policy revision, destination class, port, decision, byte counts, and exit result. Do not store request bodies, full query strings, environment dumps, or raw command output. If a diagnostic value may contain sensitive material, write [REDACTED] or omit it.

A policy file can be deliberately boring. The following is a credential-free shape; the .invalid hostnames are placeholders that cannot accidentally reach a real service.

mode: deny_by_default
policy_revision: egress-12
destinations:
  - name: source_checkout
    host: scm.example.invalid
    ports: [443]
    protocol: tcp
    purpose: source
  - name: package_mirror
    host: packages.example.invalid
    ports: [443]
    protocol: tcp
    purpose: dependency_fetch
  - name: model_gateway
    host: gateway.example.invalid
    ports: [443]
    protocol: tcp
    purpose: model_request
dns:
  resolver: approved
  permit_direct_ip: false
logging:
  record_denials: true
  record_bodies: false

Happy path. An operator records the repository, commit, task purpose, and policy revision before launching the run. The sandbox starts with the default-deny rule. The agent checks out code through the approved source destination, downloads packages through the mirror, and sends model traffic through the named gateway. Each connection is evaluated before it is opened. Tests run, the result is attached to the run record, and the sandbox is destroyed. A reviewer can answer which destination was used and why without reading the agent’s entire conversation.

Error path. Suppose a package install tries to contact an unlisted host. The resolver or egress proxy returns a denial, the command receives a clear nonzero result, and the run records a deny decision with the destination class and policy revision. The operator checks whether the package is legitimate and whether a mirror can supply it. If a new host is justified, submit a narrow policy change, review it, and rerun the same test. Do not respond by switching the sandbox to an open network or by adding a wildcard that covers unrelated services. If the policy service or proxy is unavailable, fail closed and preserve the failure record; a temporary outage is safer than an unobserved direct connection.

For a Docker-based runner, explicitly choose a reviewed network rather than inheriting the default. A no-network smoke test is useful for proving that a task does not silently depend on the Internet:

docker run --rm --network=none agent-image:reviewed run-check

That command is a test fixture, not a complete production allowlist. Approved traffic normally needs a separate controlled network, proxy, or host-level firewall. For Kubernetes, express the intent as a NetworkPolicy selecting only agent pods and allowing only the required egress peers and ports. The Kubernetes Network Policies documentation describes this selector-and-rule model; verify that the network implementation in your cluster actually enforces the policy before treating a manifest as evidence.

Use a stable, sanitized event schema so policy decisions can be compared across runtimes:

{
  "run_id": "run-7f3c",
  "policy_revision": "egress-12",
  "repository": "org/project",
  "commit": "abc1234",
  "destination_host": "packages.example.invalid",
  "destination_port": 443,
  "protocol": "tcp",
  "purpose": "dependency_fetch",
  "decision": "allow",
  "bytes_sent": 18420,
  "bytes_received": 90211,
  "dns_result": "approved",
  "exit_code": 0,
  "request_headers_redacted": true,
  "request_body_logged": false,
  "redaction_status": "complete",
  "timestamp": "2026-08-09T00:00:00Z"
}

The event records what an operator needs to reproduce a decision while leaving out material that could become an exfiltration channel. Keep the log destination outside the agent’s writeable workspace, restrict who can read it, and set a retention period that matches incident-response needs. Logging is evidence of a control, not a substitute for the control.

Who this is for

This guide is for teams that run coding agents in CI, ephemeral virtual machines, Docker containers, Kubernetes pods, or hosted repository sandboxes. It is especially useful when an agent can install packages, execute shell commands, inspect private repositories, or call an internal model gateway. Platform engineers can use the policy examples; security engineers can review the trust boundaries; application teams can supply the destination inventory and test cases.

A developer experimenting on an isolated, public repository may choose a lighter setup. The moment an agent receives private source, a write-capable workspace, or access to an internal service, treat the run as an untrusted workload and use an explicit egress contract. The same principle applies to a self-hosted runner: the runner’s network location must not be treated as proof that every outbound destination is safe.

Key takeaways

  • Deny by default, then add one purpose-specific destination at a time.
  • Make DNS, direct IP, IPv6, ports, and proxy behavior part of the test plan.
  • Review container and pod network defaults. Docker documents outgoing access on its default bridge; Kubernetes policies need a selecting rule and an enforcing network implementation.
  • Keep source checkout, package retrieval, model traffic, and telemetry as separate destination classes so one exception does not become a general permit.
  • Log decisions and outcomes, not prompts, files, headers, environment values, or full request data. GitHub’s secure use reference warns that automatic redaction is not guaranteed, recommends least privilege, and advises auditing logs after valid and invalid tests.
  • Version the policy with the workflow and require review for every expansion. A reproducible policy revision is more useful than an undocumented firewall change.

Sources checked

  • GitHub Actions Secure use reference : guidance on least-privilege workflow permissions, masking sensitive data, the limits of automatic log redaction, and reviewing logs and actions for unintended destinations.
  • Docker Networking overview : container default connectivity, user-defined networks, the none driver, DNS behavior, and network attachment choices relevant to a sandbox boundary.
  • Kubernetes Network Policies : the NetworkPolicy model for selecting pods and expressing ingress and egress peers, ports, and isolation intent.
  • NIST SP 800-207, Zero Trust Architecture : the principle that location and ownership do not create implicit trust and that authorization precedes access to a resource.

These are public documentation sources checked for this article. Their recommendations describe capabilities and principles; your runner, container runtime, network plugin, proxy, and repository permissions still need local validation.

Contract details to verify

Before enabling a coding agent on a protected repository, ask an operator to sign off on each item below:

  1. Destination inventory: Every host or service has a purpose, owner, protocol, port, and expected direction. Wildcard domains and unrestricted IP ranges have a written reason.
  2. Name resolution: The sandbox uses the approved resolver. Tests cover DNS failure, a changed address, direct-IP access, IPv6, and attempts to resolve an unlisted name.
  3. Enforcement point: The rule is enforced outside the agent process, at the container host, proxy, firewall, or cluster network layer. A process-level configuration alone is not evidence that a tool cannot bypass it.
  4. Runtime selection: Docker users have checked network mode and attachments. Kubernetes users have confirmed pod labels, policy types, peer selectors, ports, and enforcement by the installed network implementation.
  5. Repository permissions: Workflow permissions are minimal, untrusted input is not interpolated into shell source, and logs are inspected after both successful and failed tests. Link the broader permission and secret boundary checklist from the runbook.
  6. Logging contract: The event schema contains a run ID and policy revision, but no raw source, prompt, body, header, environment, or sensitive query value. Denials are retained long enough to investigate, and access to the log is narrower than access to ordinary build output.
  7. Change control: A policy update has a reviewer, a reason, a test result, and an expiry or re-review date. Emergency exceptions are isolated to one run and removed afterward.
  8. Execution context: The chosen runner and sandbox match the task’s risk. The execution-surface selection guide can help document that decision.

Failure modes

The default bridge is mistaken for isolation. A Docker container can reach outside services on the default bridge. A task that succeeds there may fail in a restricted environment, while a malicious tool can use the same route to send data out. Re-run the task with an explicitly selected network and inspect the container’s attachments. Use a controlled proxy or an isolated network for approved access, and use the network=none mode as a negative test where the task should have no network dependency.

A Kubernetes policy selects the wrong pods. Labels drift, a namespace changes, or the policy defines ingress but not egress. The manifest looks correct in review, yet the agent pod still has a route that was never intended. Test from the running pod, inspect the selected labels, and verify an actual denied connection. Keep a default-deny egress policy for the agent workload and add narrow exceptions only after the negative test passes.

A hostname rule becomes a wildcard escape hatch. Package registries and content networks can redirect or resolve to changing addresses. A rule such as “any subdomain of a large provider” is difficult to explain and may authorize unrelated services. Prefer a repository-owned mirror or a proxy with destination-aware rules. When a legitimate service changes its endpoint, update the inventory and rerun the allow and deny matrix instead of silently widening the pattern.

DNS is controlled but direct IP is not. An agent may skip the resolver, use an address learned from a previous step, or try IPv6 when only IPv4 was tested. Record the requested name, resolved address class, and decision without recording sensitive request data. Block unapproved direct routes and test both address families from inside the sandbox.

A dependency’s install script needs a second host. The package download is allowed, then a post-install step reaches a release server, telemetry endpoint, or arbitrary URL. The failure appears late and can be misdiagnosed as a broken package. Run installs in a disposable workspace, observe every destination class, and require a separate rule for any documented secondary service. If the package cannot work through the approved mirror, stop and review it rather than permitting the Internet for the whole run.

The proxy fails open. When an egress proxy is unavailable, a wrapper may fall back to the host network or direct DNS. This is a policy failure even if the task eventually succeeds. Add a startup check that proves the proxy path, make the fallback return an error, and capture the proxy-unavailable decision. A failed run with evidence is preferable to an untracked successful run.

Log masking is assumed to be perfect. GitHub warns that automatic redaction is not guaranteed and that structured secret values can be difficult to match. A command can also print an error to standard output or standard error. Keep bodies and headers out of the event schema, test redaction with valid and invalid inputs, inspect the resulting logs, and delete and rotate any sensitive value that appears. Use [REDACTED] for an unavoidable diagnostic placeholder, never a realistic credential-shaped value.

Policy and workflow revisions drift apart. The workflow points at one policy revision while the review record describes another. Include the revision in the run request and every decision event, fail startup on a mismatch, and make the revision visible in the pull request or run summary. This makes an incident reconstructable without relying on memory.

FAQ

Should every coding-agent request be allowed over HTTPS? No. HTTPS protects transport to the selected destination, but it does not identify whether that destination is appropriate for the task. Authorize a named service or controlled proxy, then limit the port and route.

Is a container with no network always the safest choice? It is a strong negative test and is appropriate for tasks that need no external service. It is not a universal production configuration: dependency installation or model calls will fail. Use it to prove the task’s dependency surface, then create the smallest reviewed network that supports the required steps.

Does a Kubernetes NetworkPolicy automatically protect every cluster? The manifest expresses intent, but enforcement depends on the network implementation and correct pod selection. Confirm both in a live test: an approved connection must work and an unapproved connection must fail.

What should a policy log contain? Use a run ID, policy revision, destination class, host or address class, port, protocol, decision, byte counts, timing, and exit result. Omit source contents, prompts, bodies, headers, environment values, and sensitive query values. Keep the schema stable so a reviewer can compare runs.

What happens when a build genuinely needs a new host? Pause the run, identify the owner and purpose, add a narrow rule with a review record, and rerun the same allow and deny tests. Do not convert a one-host need into an unrestricted network exception.

Does zero trust mean the agent cannot use a network? No. The NIST model focuses on explicit authorization for resources rather than trust inferred from a network segment or ownership. An allowlist is one practical way to make that authorization visible and testable.

Reader next step

Pick one low-risk repository and one representative agent task. Write a five-line destination inventory, set the sandbox to deny by default, and run two tests: one approved package or source operation and one intentionally unapproved destination. Confirm that the happy path completes through the expected route, the error path stops with a useful denial, and the sanitized event contains the policy revision without sensitive payloads.

Commit the policy and test cases beside the workflow, then ask a second engineer to reproduce the denial from a fresh sandbox. Expand the allowlist only when that reviewer can explain the destination, owner, port, and purpose. Repeat the exercise after changing the runner, container image, network plugin, or dependency mirror; those changes can alter the effective egress surface even when the policy text is unchanged.