Your Sandbox Shouldn’t Keep Its Install-Time Network Access Tensorlake's Sandboxes allow egress policy to be replaced on a running sandbox with a single update call, enabling network access to be revoked after installation. The swap is atomic with no enforcement gap, and the policy is enforced host-side, not inside the guest. This addresses the problem of AI agents retaining install-time network access during untrusted code execution. Your AI agent needed internet access to install a dependency. Why should it still have that access when it starts running code you never wrote? Say your setup step needs pypi.org, files.pythonhosted.org, and a Git host. The code your model writes next needs one internal API and nothing else. Both phases run in the same sandbox under the same firewall rules, because the network policy was decided before either phase existed. If the policy stays unchanged after installation, the untrusted phase inherits the installer’s network reach and keeps it until the sandbox dies. The broader requirement wins simply because the narrower one would have broken setup. That’s the problem with treating network policy as part of the environment spec, alongside CPU, memory, and disk. For workloads where trust level changes during execution, permissions should follow the phase, not the sandbox. Setting network policy at environment creation feels natural; it’s how we usually think about containers and VMs: give the environment a set of resources and permissions, then leave them alone until it goes away. But agent workloads don’t stay in one trust state. During setup, you run dependencies and tools you explicitly chose. A few minutes later, the same sandbox might execute code generated by a model or submitted by a user. Those phases can need very different access, but they sit behind the same firewall. Keep one policy for both, and the broader permission set carries into the less-trusted phase, not because the sandbox requires it, but because the policy was tied to the sandbox instead of to the work happening inside it. There are a few obvious workarounds, none particularly attractive: What I actually want is simpler: keep the sandbox, change its egress policy when the phase changes, and see exactly what policy is active at each point. An egress policy defines where a sandbox can make outbound connections, and those rules don’t have to stay the same for the sandbox’s entire lifetime. That requires enforcement to live outside the workload, with the transition controlled by the system orchestrating the run. This is where Tensorlake’s Sandboxes are useful: the egress policy can be replaced on a running sandbox with a single update call. I’m using Tensorlake here because the behavior is explicit enough in the documentation and SDK source to verify what actually happens, rather than filling gaps with assumptions. Before trusting a mechanism like this in a phased design, I want to know what happens when something goes wrong. Four things matter: Tensorlake documents the first three directly: the swap is atomic with no enforcement gap, sending a policy object replaces the entire policy, and a policy naming an unresolvable hostname is rejected while the previous policy stays enforced. The fourth is more about how you design the control path than a guarantee Tensorlake gives you. The update runs through an authenticated API, so keeping that path outside the sandbox is up to how you handle credentials, code inside the sandbox could still call the API if it holds a key with enough permissions. The test is mine. The behavior it checks is not. You can change a sandbox’s egress policy without recreating or suspending it. The new policy applies to the running firewall in a single atomic swap, with no gap where old rules are gone and new ones haven’t taken effect. The important detail is where enforcement happens. In the Python SDK, NetworkConfig is enforced host-side, per sandbox, not inside the guest's own network stack. Changing routes or firewall rules from inside the sandbox doesn't change the policy; doing that would require calling the same authenticated API the orchestrator uses, which makes credential placement a separate security concern. The firewall is also stateful: established and related connections remain permitted, so changing the policy doesn’t cut off traffic already in progress. The live update surface is deliberately limited to name, exposed ports, unauthenticated access for those ports, and egress policy. CPU, memory, and disk are fixed at creation and require a new sandbox to change. Egress policy is one of the few resource properties you can change while running, and a replacement naming an unresolvable hostname is rejected outright, leaving the sandbox on its prior policy in full. A rejected update leaves you where you already were, never somewhere weaker. The network argument is tri-state: You pass Result Nothing omit network Current policy unchanged. Update name or ports freely. A policy object The entire policy is replaced by what you sent. An explicit clear The sandbox returns to unrestricted egress. Updates replace rather than merge, so every update has to express the complete intended policy for that phase. Clearing removes restrictions rather than imposing them, so a phase with no network at all is allow internet access=false with an empty allow out, not a clear. python from tensorlake.sandbox import CLEAR NETWORK POLICY, NetworkConfig, Sandboxsandbox = Sandbox.connect "