For a year, GitHub Copilot's autonomous coding agent worked from inside a box GitHub built and watched. It opened draft pull requests, ran your tests, installed your dependencies — all inside a cloud sandbox with a managed firewall standing between the agent and everything except a preapproved list of package registries. Then, on October 28, 2025, GitHub shipped the exception: point the coding agent at your own Actions Runner Controller (ARC) fleet instead, and it can now reach your internal npm mirror, your private Maven repo, an on-prem service no public sandbox could ever touch. By April 2026, organizations could set that self-hosted fleet as the default runner for every repo at once.
Here's the part that doesn't make it into the changelog headline: to get that internal reach, you have to turn GitHub's firewall off. Not narrow it, not add an allowlist entry — disable it. The trust boundary that used to be GitHub's job becomes yours, in full, the moment you point copilot-setup-steps.yml at a scale set you run. What follows is what that boundary looked like before, what specifically breaks when you flip the switch, and the three concrete ways teams get the replacement wrong.
What GitHub's Cloud Sandbox Actually Does
The default coding-agent environment isn't just "runs somewhere GitHub controls" — it has a specific, documented job. GitHub's built-in agent firewall exists to limit the coding agent's outbound network access and blunt two specific threats: prompt-injection-driven data exfiltration, and an agent reaching somewhere it has no business reaching.
Concretely, that firewall:
- Allowlists common package registries by default — npm, PyPI, and similar sources the agent needs to install your dependencies, enabled automatically so routine builds don't break.
- Blocks local networks and cloud metadata endpoints outright — the two paths a compromised agent process would use to pivot from "read some code" to "read cloud credentials" or "reach an internal service that was never meant to be internet-facing."
- Runs in an ephemeral, isolated workspace per task, so there's no state — and no accumulated blast radius — carried from one coding-agent run to the next.
- As of April 2026, is configurable at the organization level — an admin can set the firewall to
Enabled,Disabled, orLet repositories decide, and do the same for the recommended allowlist, rolling out consistent defaults across every repo rather than trusting each team to configure it correctly on its own.
That's a real security product, not a rubber stamp. It's also, by design, generic — it knows about public package registries and cloud metadata endpoints because those are the same for every GitHub customer. It has no idea your team's builds also need npm.internal.yourco.com, or that your test suite calls a staging API that only resolves inside your VPC. For any team whose real build touches real internal infrastructure, the sandbox's greatest strength — a firewall that's the same for everyone — is also exactly what makes it useless.
What Flipping to Self-Hosted Actually Changes
That's the gap Actions Runner Controller support closes, and the mechanism is more blunt than "add an internal-hosts exception." GitHub's own documentation states it plainly: the coding agent's native firewall is not compatible with self-hosted runners. To run the coding agent on your own ARC fleet at all, you have to go into the repository's coding-agent settings and disable the firewall — there's no partial mode, no "keep the metadata-endpoint block but open everything else." It's off, or you don't get self-hosted runners.
In exchange, the setup gets genuinely useful. copilot-setup-steps.yml is a standard GitHub Actions workflow file with one required job (copilot-setup-steps) that runs before the agent starts work, and its runs-on: field can now target an ARC scale set the same way any other workflow would. Once that's wired up, the agent's environment inherits whatever your runner fleet already sees: an internal npm or Maven mirror, a private PyPI proxy, an on-prem API your production services already call. It also inherits whatever network ACLs, scanning, and logging you already run at the runner-fleet level — assuming you have any, which is exactly the assumption the next section stress-tests.
Sit with what it means that this was GitHub's answer. GitHub isn't a team without security resources — it built the managed firewall, it maintains the metadata-endpoint blocklist, it has every incentive to keep the coding agent's blast radius inside infrastructure it controls rather than shipping customers an off switch. It shipped the off switch anyway, because a firewall that only knows about public registries was never going to cover a real company's real internal stack — every private registry, every internal API, every on-prem tool is a one-off no generic allowlist could anticipate. Rather than try to extend the managed firewall to cover that long tail, GitHub's answer was to hand the whole boundary back to the operator. The exception was always going to swallow the rule for any coding agent expected to do real engineering work; GitHub just made that explicit instead of pretending the sandbox would eventually catch up.
Three Ways ARC Quietly Stops Protecting You
None of this is a knock on ARC itself — it's a capable, widely deployed way to run self-hosted GitHub Actions on Kubernetes. The problem is that its safe defaults require configuration GitHub's quick-start docs don't force on you, and a coding agent now inherits whatever gap is left. Three specific ones matter most once a firewall is no longer catching the overflow.
1. Runners that aren't actually ephemeral. ARC's Helm chart doesn't make ephemeral runners the loud, unmissable default — RUNNER_EPHEMERAL: "true" is a setting teams have to know to set, not a behavior baked into a quick-start deploy. Skip it and you get persistent runner pods that execute job after job on the same filesystem, which means secrets, tokens, and any file a previous coding-agent task pulled from your internal registry can still be sitting there when the next task starts. GitHub's cloud sandbox gives you a clean workspace per task by default; a naive ARC deployment gives you the opposite unless you explicitly ask for it.
2. Runner pods that inherit more privilege than they should. If a runner's pod template doesn't set serviceAccountName: arc-runner, Kubernetes falls back to the namespace's default service account — and if the arc-system (controller) and arc-runners (runner) namespaces get collapsed into one, a common quick-start shortcut, the coding agent's compute can end up running under the same service account as the controller that manages your entire runner fleet. An agent that's supposed to check out a repo and run tests now has a credential blast radius that includes the thing provisioning every other runner.
3. No NetworkPolicy restricting egress. This is the one that most directly replaces what GitHub's firewall used to do. Kubernetes NetworkPolicies are what actually constrain where a runner pod's traffic can go — and they're opt-in. Deploy ARC without them and a compromised coding-agent task (via prompt injection, a malicious dependency, whatever the entry point) has exactly the same unrestricted egress as any other pod in your cluster, because nothing is narrowing it. GitHub's firewall blocked cloud metadata endpoints and local networks by default; the self-hosted equivalent doesn't exist until you write it.
The fix for all three is the same shape: a dedicated namespace for runner pods (not shared with the ARC controller), a scoped ServiceAccount bound to a minimal ClusterRole, RUNNER_EPHEMERAL: "true" set explicitly, and a NetworkPolicy that allows only the internal registries and services the coding agent actually needs — not "the cluster's default egress," which for most clusters means "everywhere." That's four concrete settings, not a philosophy, and every one of them is something the ARC quick-start path leaves for you to add later.
The Same Trade, Without the Bolt-On
This isn't just a GitHub Copilot story — it's the shape of the trade-off for anyone shipping an agent-operable deploy surface at all. GitHub built a managed firewall for the cloud-hosted default, then had to ship an explicit off switch the moment operators needed the agent to reach real internal infrastructure, because a firewall calibrated for every customer at once can't also be scoped tightly to any one of them.
A self-hosted PaaS running its own Model Context Protocol deploy and rollback tooling on infrastructure it already owns doesn't face that same bolt-on-then-remove sequence. If the platform's tenant workloads already run on a Cluster API-managed fleet — with NetworkPolicies isolating tenant traffic, RBAC scoping what each service account can touch, namespaces separating what shouldn't share a blast radius — an agent's own deploy tool calls can run inside those same boundaries from day one, not as a generic vendor firewall grafted on top and then switched off the first time someone needs to reach something internal. Bex.co's take on this is to keep that boundary as the same infrastructure primitive the platform operator already controls for every other tenant workload — scoped, short-lived deploy tokens and the fleet's own network policy, not a separate agent-specific firewall product with its own off switch.
The lesson generalizes past Copilot specifically: any team wiring an agent into infrastructure that matters should ask, before the agent's first tool call, exactly what boundary is doing the work of "no, not that" — and whether that boundary is one they already own and control, or one they're borrowing from a vendor that might ship its own exception clause later. GitHub's answer, in the end, was a well-documented off switch and a set of Kubernetes primitives operators have to assemble themselves. That's not a knock on the feature — internal registry access is a real requirement, and GitHub shipped a real way to get it. It's a reason to treat "self-hosted runners are now supported" as the start of a security checklist, not the end of one.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with an MCP-driven deploy API scoped to the same infrastructure boundaries the platform already enforces for tenant workloads. Star the repo on GitHub or deploy your first app today.
Sources
- Copilot coding agent now supports self-hosted runners — GitHub Changelog
- Organization runner controls for Copilot cloud agent — GitHub Changelog
- Organization firewall settings for Copilot cloud agent — GitHub Changelog
- Customizing or disabling the firewall for GitHub Copilot coding agent — GitHub Docs
- About customizing Copilot coding agent's development environment — GitHub Docs
- Actions Runner Controller (ARC) — GitHub
- GitHub Actions Runner Controller Security: Ephemeral Runners and Pod Isolation in Kubernetes



