Skip to content

Managed network proxy should provide allowlisted DNS resolution inside Linux sandbox #22387

@jdr45

Description

@jdr45

What variant of Codex are you using?

CLI

What feature would you like to see?

Summary

Codex's managed network proxy can allow HTTP(S)/SOCKS traffic to specific domains, but process-local DNS APIs inside the Linux sandbox still fail. This breaks clients that need DNS resolution or canonicalization before making an otherwise allowlisted proxied request.

A concrete example is Kerberos/SPNEGO auth: the HTTP(S) request reaches the allowlisted service through the proxy, but the auth stack cannot construct the correct service principal because local DNS/canonicalization fails inside the sandbox.

Environment

  • Platform: Linux
  • Sandbox: managed permissions profile with network proxy enabled
  • Config shape:
default_permissions = "workspace"

[permissions.workspace.filesystem]
":root" = "read"
":tmpdir" = "write"

[permissions.workspace.filesystem.":project_roots"]
"." = "write"

[permissions.workspace.network]
enabled = true
mode = "full"
allow_local_binding = true
allow_upstream_proxy = true

[permissions.workspace.network.domains]
"internal-symbols.example.corp" = "allow"
"internal-data.example.corp" = "allow"

Observed Behavior

The managed proxy is active:

CODEX_NETWORK_PROXY_ACTIVE=1

It correctly enforces the allowlist for non-allowed hosts:

$ curl -I -v https://www.google.com
> CONNECT www.google.com:443 HTTP/1.1
< HTTP/1.1 403 Forbidden
< x-proxy-error: blocked-by-allowlist

Allowlisted HTTP(S) hosts are reachable through the proxy. For example, a non-Kerberos allowlisted internal API succeeds.

However, local DNS APIs still fail inside the sandbox:

import socket

socket.getaddrinfo("internal-data.example.corp", 443)
# socket.gaierror: [Errno -2] Name or service not known

Canonicalization also differs inside vs. outside the sandbox:

socket.getfqdn("internal-data.example.corp")
# inside sandbox:  "internal-data.example.corp"
# outside sandbox: "backend-canonical-host.example.corp"

Consequence

HTTP/SOCKS proxying is not enough for all clients. Many libraries perform local DNS resolution or canonicalization before or during a request, including:

  • Kerberos/SPNEGO clients selecting a service principal
  • Java, Node, Python, git, curl, and other clients using libc/NSS
  • Tools that do not support remote DNS through SOCKS5
  • Libraries that need canonical hostnames before connecting

For example, a Kerberos-backed internal client constructs auth like:

requests_kerberos.HTTPKerberosAuth(
    hostname_override=socket.getfqdn(urlparse(url).hostname),
    mutual_authentication=requests_kerberos.OPTIONAL,
)

Inside the sandbox, this builds the wrong service principal because DNS canonicalization fails, and the request returns 401. Outside the sandbox, the same request succeeds. If the canonical hostname discovered outside the sandbox is hardcoded inside the sandbox, the same allowlisted request succeeds through the Codex managed proxy, confirming that HTTP(S), TLS, and the proxy tunnel are otherwise working.

Expected Behavior

When the managed proxy allows a domain, sandboxed processes should have a way for normal DNS APIs to resolve and canonicalize that domain, without enabling unrestricted network access.

Ideally Codex would provide an allowlist-aware DNS forwarder in the sandbox network namespace, so unmodified libc/NSS users such as getaddrinfo, getfqdn, Java, Node, git, curl, and Kerberos/SPNEGO clients can resolve allowlisted domains.

Security Considerations

Raw DNS egress could be an exfiltration channel, so unrestricted UDP/TCP 53 may be undesirable.

A safer design might be a Codex-managed DNS proxy/forwarder:

  • sandbox /etc/resolv.conf points at a resolver address inside the sandbox namespace
  • the resolver listens on port 53 inside the namespace, but can forward via an unprivileged host-side service
  • DNS handling preserves the same security intent as the managed network allowlist, without creating a broad DNS exfiltration channel
  • CNAME/PTR/canonicalization behavior needed by common client stacks is supported in a principled way
  • denied or unsupported lookups fail clearly and emit policy telemetry similar to HTTP/SOCKS proxy decisions

Minimal Repro

  1. Configure a managed network proxy profile with one allowlisted internal HTTPS host.

  2. Restart Codex and confirm the proxy is active:

    CODEX_NETWORK_PROXY_ACTIVE=1
  3. Confirm a non-allowed public host is blocked by proxy policy:

    $ curl -I -v https://www.google.com
    < HTTP/1.1 403 Forbidden
    < x-proxy-error: blocked-by-allowlist
  4. Confirm the allowlisted HTTPS host is reachable through the proxy.

  5. In the same sandbox, test local DNS:

    import socket
    
    socket.getaddrinfo("internal-data.example.corp", 443)

    Actual:

    socket.gaierror: [Errno -2] Name or service not known

    Expected:

    The allowlisted domain resolves, or Codex provides an equivalent allowlist-aware DNS/canonicalization path.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsandboxIssues related to permissions or sandboxing

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions