Repository navigation
AI-1667: proxy broker uses Daytona's IP allow list - #1122
Merged
Merged
Conversation
…ow list (AI-1667) Under a domain allow list Daytona's netleash ends TLS itself and refuses the proxy's certificate for a granted host, so GitHub failed on staging. With broker proxy the sandbox now gets NetworkAllowList = <proxy IP>/32, no domain list and no OutboundProxyUrl; every run's env names the proxy with the sandbox's credential. proxy_public_url must be an IPv4 address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…behind the proxy; say what the sandbox still reaches Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linear: AI-1667 (parent AI-1572)
Why
With
code_sandbox.broker: proxy, a sandbox call to a granted host (GitHub) fails on staging. Daytona's domain allow list brings in its netleash, which ends TLS itself and refuses the proxy's certificate for a granted host:502in the sandbox,tls: bad certificatein the router log (staging E2E, 2026-10-22 00:29Z). A live probe (2026-10-22 01:02–01:08Z) shows that Daytona's network allow list alone (<ip>/32) limits all TCP and UDP to that address, passes TLS as it is (real certificates), and injects no proxy or CA env. Daytona refuses a domain list and a network list together (400 mutually exclusive). So the sandbox now reaches our proxy by its IP and nothing else.How it works
sequenceDiagram participant Router as Router (session, run_code) participant Daytona as Daytona API participant Sandbox as Sandbox code participant Proxy as Router egress proxy (IPv4:8091) participant GitHub as api.github.com Router->>Daytona: create sandbox, NetworkAllowList = proxy IP/32, no DomainAllowList, no OutboundProxyUrl Router->>Daytona: every command and CodeRun with env HTTPS_PROXY = http://sbx:credential@IP:8091 and the CA vars Sandbox->>Proxy: CONNECT api.github.com:443 with Proxy-Authorization (no DNS in the sandbox) Proxy->>Proxy: record by credential, grant check Proxy-->>Sandbox: TLS with a certificate from the router CA Sandbox->>Proxy: GET /user, Authorization Bearer va_ph_... Proxy->>GitHub: GET /user, Authorization Bearer token (resolved now) GitHub-->>Proxy: 200 Proxy-->>Sandbox: 200, token turned back into the placeholder Sandbox->>Proxy: CONNECT pypi.org:443 (allowed domain) Proxy->>Sandbox: blind tunnel, no token (unchanged from #1113)DomainAllowList= grants' hosts + allowed domains,OutboundProxyUrl= proxy with credentialNetworkAllowList=<proxy IPv4>/32, nothing elseHTTPS_PROXYetc.)ca.crt, else image roots/etc/ssl/certs/ca-certificates.crt) + router CAproxy_public_urlhttp://host:porthttp://<public IPv4>:port; host name, IPv6, a non-public address, a bad port or a path/query/fragment stops the router at startbroker: daytonaRule → test
NetworkAllowList= proxy/32, no domain list, noOutboundProxyUrl, noNetworkBlockAlldaytona.goparams,domainsdaytona.TestProxySuite/TestTheSandboxReachesTheProxyAlone,TestAGrantTheBrokerLeavesOutHasNoEnvVar; the config'snetwork_allow_list(10.0.0.0/8) is dropped behind the proxy (case in the first test);session.TestSandboxGrantsSuite/TestTheProxyBrokerSendsTheSandboxThroughTheProxyHTTPS_PROXY/HTTP_PROXY/lower case = proxy with credential,NO_PROXY/no_proxy= loopbackegress/broker.goPrepareegress.TestBrokerSuite/TestEveryRunGoesThroughTheProxyAndTrustsTheCA; every proxy test builds its client fromRunEnv["HTTPS_PROXY"]ca.crtnever trustedegress/broker.gobundleegress.TestBrokerSuite/TestTheBundleHoldsTheSandboxsRootsAndTheCAproxy_public_urlishttp://<public IPv4>:port: no host name, IPv6, IPv4-mapped IPv6, 0.0.0.0, loopback, RFC 1918, link-local (169.254.169.254), broadcast; port 1-65535; no path, query, fragmentconfig.ProxyURL(config.go), used byValidateandegress.NewBrokerconfig.TestConfigSuite/TestTheProxyBrokersProxyIsAnIPv4Address,TestTheProxyBrokerNeedsTheProxysURLAndCA;egress.TestBrokerSuite/TestAProxyURLItCannotUseIsRefusedbroker: daytonasends Daytona what it did beforedaytona.TestSecretsSuite/TestDaytonasBrokerSendsDaytonaWhatItDidBefore(extended:{},network: true,network_allow_list, expected bodies from base 4588e62)Each rule was mutation-checked (20 mutations, all killed).
Known limits
HTTPS_PROXYreaches our proxy in a network-list-only sandbox end to end, and that GitHub then answers 200. Root changing routes to get around the network list: unverified.Docs:
acceleration/internal/sandbox/egress/AGENTS.md,.claude/skills/connectors/SKILL.md,acceleration/README.md.🤖 Generated with Claude Code