Summary
AWF (@github/awf) has merged an opt-in --network-isolation egress model (github/gh-aw-firewall#5237) that enforces egress via Docker network topology — an --internal awf-net network with a dual-homed Squid sidecar — instead of host iptables / NET_ADMIN. The primary motivation is ARC (Actions Runner Controller) Kubernetes runners with a DinD sidecar, where NET_ADMIN and host-iptables are unavailable.
The gh-aw compiler now needs a companion change so generated workflows can opt into this mode. This is the §8.2 work item from the AWF design note (docs/network-isolation-design.md).
AWF-side surface already shipped (what the compiler must target)
- CLI flag:
--network-isolation.
- Config-file equivalents (consumed via
awf --config): network.isolation: true and network.topologyAttach: [<container names>] (added to the canonical awf-config.schema.json; topologyAttach requires isolation: true).
- Repeatable CLI flag
--topology-attach <name> — passes gateway/DIFC container names so AWF runs docker network connect awf-net <container> after startup.
- Deterministic internal network name is
awf-net.
- Fail-stop preflight: AWF aborts with a clear "platform unsupported" message if no Docker daemon is reachable (specializes for the ARC k8s-native fingerprint). Network-isolation is only supported when a DinD/Docker daemon is present.
Required compiler changes (§8.2)
Per docs/network-isolation-design.md §8.2:
- Launch mcpg gateway mode as a bridge container with a static
awf-net-compatible IP (not --network host); drop the --add-host host.docker.internal:127.0.0.1 loopback trick.
- Launch DIFC / cli-proxy mode as a bridge container with
-p 127.0.0.1:18443:18443 (published for host pre-steps) instead of --network host.
- Emit the network-attach handshake: pass the gateway/DIFC container names to AWF via
--topology-attach <name> (or network.topologyAttach), and point the agent's MCP gateway address + cli-proxy DIFC target at the internal awf-net addresses.
- When network-isolation is set, stop passing
--enable-host-access --allow-host-ports … / --difc-proxy-host host.docker.internal:…; pass the internal equivalents instead.
- Under ARC/DinD, point pre-step
GH_HOST at the dind-reachable DIFC address rather than localhost.
Note: there are two mcpg instances — gateway mode (agent traffic) and proxy mode (launched early in a pre-agent step so pre-step gh CLI commands are captured). Both need the bridge/internal-address treatment under isolation.
Concrete touch points in this repo (pkg/workflow/)
- AWF flag emission —
awf_helpers.go:616-652: --enable-host-access (616-619), --allow-host-ports 80,443,<mcpPort> (621-635), --difc-proxy-host host.docker.internal:18443 + --difc-proxy-ca-cert (644-648). These are the flags §8.2 changes under isolation.
- AWF config struct —
awf_config.go:154-257 (AWFConfigFile / AWFNetworkConfig). A new isolation toggle / topologyAttach would serialize here. Config JSON assembled at awf_config.go:322-480.
- MCP gateway container launch —
mcp_setup_generator.go:741-786: docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 … (762-763). Gateway address selection at mcp_setup_generator.go:631-652.
- DIFC / cli-proxy launch —
compiler_difc_proxy.go:468-526 (buildStartCliProxyStepYAML) + start_cli_proxy.sh; AWF→proxy wiring via host.docker.internal:18443 (compiler_difc_proxy.go:468-470, awf_helpers.go:644-648); proxy env routes GitHub API at compiler_difc_proxy.go:311-320.
- Frontmatter → compiler threading — schema
pkg/parser/schemas/main_workflow_schema.json; compiler structs pkg/workflow/compiler_types.go:453-541 (WorkflowData), engine.go:28-80, sandbox.go:34-62.
- Embedded AWF config schema sync —
pkg/workflow/schemas/awf-config.schema.json (//go:embed at awf_config.go:74-75) must gain the new network.isolation / network.topologyAttach fields. Drift procedure: specs/awf-config-sources-spec.md:92-130.
- Golden fixtures —
pkg/workflow/testdata/wasm_golden/…; regenerate with make update-wasm-golden (i.e. go test -v -run='^TestWasmGolden_' ./pkg/workflow -update).
Open design questions
- Enablement surface: explicit user-facing frontmatter toggle (e.g.
engine.firewall.network-isolation) vs. auto-enable under a detected ARC/DinD condition. (AWF keeps it opt-in/experimental today.)
- Handshake mechanism:
--topology-attach <name> flags vs. network.topologyAttach config array.
- Static IP assignment for the gateway/DIFC bridge containers within
awf-net, vs. attaching by container name and relying on Docker DNS.
Out of scope (§8.3, tracked separately)
- ARC
containerMode: kubernetes (no Docker daemon) — unsupported by policy; AWF fails stop.
- Forcing child MCP-server egress through Squid — deprioritized.
References
Summary
AWF (
@github/awf) has merged an opt-in--network-isolationegress model (github/gh-aw-firewall#5237) that enforces egress via Docker network topology — an--internalawf-netnetwork with a dual-homed Squid sidecar — instead of host iptables /NET_ADMIN. The primary motivation is ARC (Actions Runner Controller) Kubernetes runners with a DinD sidecar, whereNET_ADMINand host-iptables are unavailable.The gh-aw compiler now needs a companion change so generated workflows can opt into this mode. This is the §8.2 work item from the AWF design note (
docs/network-isolation-design.md).AWF-side surface already shipped (what the compiler must target)
--network-isolation.awf --config):network.isolation: trueandnetwork.topologyAttach: [<container names>](added to the canonicalawf-config.schema.json;topologyAttachrequiresisolation: true).--topology-attach <name>— passes gateway/DIFC container names so AWF runsdocker network connect awf-net <container>after startup.awf-net.Required compiler changes (§8.2)
Per
docs/network-isolation-design.md§8.2:awf-net-compatible IP (not--network host); drop the--add-host host.docker.internal:127.0.0.1loopback trick.-p 127.0.0.1:18443:18443(published for host pre-steps) instead of--network host.--topology-attach <name>(ornetwork.topologyAttach), and point the agent's MCP gateway address + cli-proxy DIFC target at the internalawf-netaddresses.--enable-host-access --allow-host-ports …/--difc-proxy-host host.docker.internal:…; pass the internal equivalents instead.GH_HOSTat the dind-reachable DIFC address rather thanlocalhost.Note: there are two mcpg instances — gateway mode (agent traffic) and proxy mode (launched early in a pre-agent step so pre-step
ghCLI commands are captured). Both need the bridge/internal-address treatment under isolation.Concrete touch points in this repo (
pkg/workflow/)awf_helpers.go:616-652:--enable-host-access(616-619),--allow-host-ports 80,443,<mcpPort>(621-635),--difc-proxy-host host.docker.internal:18443+--difc-proxy-ca-cert(644-648). These are the flags §8.2 changes under isolation.awf_config.go:154-257(AWFConfigFile/AWFNetworkConfig). A new isolation toggle /topologyAttachwould serialize here. Config JSON assembled atawf_config.go:322-480.mcp_setup_generator.go:741-786:docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 …(762-763). Gateway address selection atmcp_setup_generator.go:631-652.compiler_difc_proxy.go:468-526(buildStartCliProxyStepYAML) +start_cli_proxy.sh; AWF→proxy wiring viahost.docker.internal:18443(compiler_difc_proxy.go:468-470,awf_helpers.go:644-648); proxy env routes GitHub API atcompiler_difc_proxy.go:311-320.pkg/parser/schemas/main_workflow_schema.json; compiler structspkg/workflow/compiler_types.go:453-541(WorkflowData),engine.go:28-80,sandbox.go:34-62.pkg/workflow/schemas/awf-config.schema.json(//go:embedatawf_config.go:74-75) must gain the newnetwork.isolation/network.topologyAttachfields. Drift procedure:specs/awf-config-sources-spec.md:92-130.pkg/workflow/testdata/wasm_golden/…; regenerate withmake update-wasm-golden(i.e.go test -v -run='^TestWasmGolden_' ./pkg/workflow -update).Open design questions
engine.firewall.network-isolation) vs. auto-enable under a detected ARC/DinD condition. (AWF keeps it opt-in/experimental today.)--topology-attach <name>flags vs.network.topologyAttachconfig array.awf-net, vs. attaching by container name and relying on Docker DNS.Out of scope (§8.3, tracked separately)
containerMode: kubernetes(no Docker daemon) — unsupported by policy; AWF fails stop.References
docs/network-isolation-design.md§8.2 (githubnext/gh-aw-firewall).