Skip to content

Network isolation and permissions

Network isolation is provided by AWF (Agentic Workflow Firewall), which provides L7 (HTTP/HTTPS) egress control using Squid proxy and Docker containers. AWF restricts network access to a whitelist of approved domains.

The ado-aw compiler binary is distributed via GitHub Releases with SHA256 checksum verification. The AWF binary is distributed via GitHub Releases with SHA256 checksum verification. Docker is sourced via the DockerInstaller@0 ADO task.

The following domains are always allowed. Most are defined in CORE_ALLOWED_HOSTS in allowed_hosts.rs; host.docker.internal is the exception — it is added by the standalone compiler in generate_allowed_domains (src/compile/common.rs) because standalone pipelines always use MCPG, which needs host access from the AWF container:

Host PatternPurpose
dev.azure.com, *.dev.azure.comAzure DevOps
vstoken.dev.azure.comAzure DevOps tokens
vssps.dev.azure.comAzure DevOps identity
*.visualstudio.comVisual Studio services
*.vsassets.ioVisual Studio assets
*.vsblob.visualstudio.comVisual Studio blob storage
*.vssps.visualstudio.comVisual Studio identity
pkgs.dev.azure.com, *.pkgs.dev.azure.comAzure DevOps Artifacts/NuGet
aex.dev.azure.com, aexus.dev.azure.comAzure DevOps CDN
vsrm.dev.azure.com, *.vsrm.dev.azure.comVisual Studio Release Management
github.comGitHub main site
api.github.comGitHub API
*.githubusercontent.comGitHub raw content
*.github.comGitHub services
*.copilot.github.comGitHub Copilot
*.githubcopilot.comGitHub Copilot
copilot-proxy.githubusercontent.comGitHub Copilot proxy
login.microsoftonline.comMicrosoft identity (OAuth)
login.live.comMicrosoft account authentication
login.windows.netAzure AD authentication
*.msauth.net, *.msftauth.netMicrosoft authentication assets
*.msauthimages.netMicrosoft authentication images
graph.microsoft.comMicrosoft Graph API
management.azure.comAzure Resource Manager
*.blob.core.windows.netAzure Blob storage
*.table.core.windows.netAzure Table storage
*.queue.core.windows.netAzure Queue storage
*.applicationinsights.azure.comApplication Insights telemetry
*.in.applicationinsights.azure.comApplication Insights ingestion
dc.services.visualstudio.comVisual Studio telemetry
rt.services.visualstudio.comVisual Studio runtime telemetry
config.edge.skype.comConfiguration
host.docker.internalMCP Gateway (MCPG) on host — added by the standalone compiler, not part of CORE_ALLOWED_HOSTS

Agents can specify additional allowed hosts in their front matter using either ecosystem identifiers or raw domain patterns:

network:
allowed:
- python # Ecosystem identifier -- expands to Python/PyPI domains
- rust # Ecosystem identifier -- expands to Rust/crates.io domains
- "*.mycompany.com" # Raw domain pattern
- "api.external-service.com" # Raw domain

Ecosystem identifiers are shorthand names that expand to curated domain lists for common language ecosystems and services. The domain lists are sourced from gh-aw and kept up to date via an automated workflow.

Available ecosystem identifiers include:

IdentifierIncludes
defaultsCertificate infrastructure, Ubuntu mirrors, common package registries
githubGitHub domains (github.com, *.githubusercontent.com, etc.)
localLoopback addresses (localhost, 127.0.0.1, ::1)
containersDocker Hub, GHCR, Quay, Kubernetes
linux-distrosDebian, Alpine, Fedora, CentOS, Arch Linux package repositories
dev-toolsCI/CD and developer tool services (Codecov, Shields.io, Snyk, etc.)
pythonPyPI, pip, Conda, Anaconda
rustcrates.io, rustup, static.rust-lang.org
nodenpm, Yarn, pnpm, Bun, Deno, Node.js
goproxy.golang.org, pkg.go.dev, Go module proxy
javaMaven Central, Gradle, JDK downloads
dotnetNuGet, .NET SDK
rubyRubyGems, Bundler
swiftSwift.org, CocoaPods
terraformHashiCorp releases, Terraform registry

Additional ecosystems: bazel, chrome, clojure, dart, deno, elixir, fonts, github-actions, haskell, julia, kotlin, latex, lean, lua, node-cdns, ocaml, perl, php, playwright, powershell, python-native, r, scala, zig.

The full domain lists are defined in src/data/ecosystem_domains.json.

All hosts (core + MCP-specific + ecosystem expansions + user-specified) are combined into a comma-separated domain list passed to AWF’s --allow-domains flag.

The network.blocked field removes hosts from the combined allowlist. Both ecosystem identifiers and raw domain strings are supported. Blocking an ecosystem identifier removes all of its domains. Blocking a raw domain uses exact-string matching — blocking "github.com" does not also remove "*.github.com".

network:
allowed:
- python
- node
blocked:
- python # Remove all Python ecosystem domains
- "github.com" # Remove exact domain
- "*.github.com" # Remove wildcard variant too

ADO does not support fine-grained permissions — there are two access levels: blanket read and blanket write. Tokens are minted from ARM service connections; System.AccessToken is never used for agent or executor operations.

Exception: The trigger filter gate step (Setup job) uses System.AccessToken for two purposes: (1) self-cancelling the build when filters don’t match (PATCH to _apis/build/builds/{id}), and (2) fetching PR metadata for Tier 2 filters (labels, draft status, changed files). This runs in the Setup job before the agent starts, outside the AWF sandbox. The pipeline must have “Allow scripts to access the OAuth token” enabled for this to work. This is a deliberate scoped exception — the token is not passed to the agent or executor.

permissions:
read: my-read-arm-connection # Stage 1 agent -- read-only ADO access
write: my-write-arm-connection # Stage 3 executor -- write access for safe-outputs
  • permissions.read: Mints a read-only ADO-scoped token given to the agent inside the AWF sandbox (Stage 1). The agent can query ADO APIs but cannot write.
  • permissions.write: Mints a write-capable ADO-scoped token used only by the executor in Stage 3 (SafeOutputs job). This token is never exposed to the agent.
  • Both omitted: No ADO tokens are passed anywhere. The agent has no ADO API access.

If write-requiring safe-outputs (create-pull-request, create-work-item) are configured but permissions.write is missing, compilation fails with a clear error message.

# Agent can read ADO, safe-outputs can write
permissions:
read: my-read-sc
write: my-write-sc
# Agent can read ADO, no write safe-outputs needed
permissions:
read: my-read-sc
# Agent has no ADO access, but safe-outputs can create PRs/work items
permissions:
write: my-write-sc