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 generate_allowed_domains (src/compile/common.rs) for any target that uses AWF (standalone and 1es targets), but not for job or stage targets. AWF-sandboxed agents need host.docker.internal to reach MCPG and SafeOutputs MCP servers running on the host:

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) and SafeOutputs on host — added for AWF targets (standalone, 1es), not part of CORE_ALLOWED_HOSTS
aka.msMicrosoft link shortener (used by az subcommand help/metadata) — contributed by the always-on Azure CLI extension

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. ARM service connections are used to mint scoped tokens for the agent (permissions.read) and optionally for the executor (permissions.write). The Stage 3 executor also uses the pipeline’s built-in $(System.AccessToken) as its default write token when no permissions.write override is configured.

Note: 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). The Stage 3 executor also uses System.AccessToken as its default write token. In both cases the pipeline must have “Allow scripts to access the OAuth token” enabled. The agent (Stage 1) never receives System.AccessToken — this trust boundary ensures the AI agent cannot directly perform write operations.

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 (optional): Overrides the Stage 3 executor’s default $(System.AccessToken) with an ARM-minted write token (SC_WRITE_TOKEN). Use this for cross-org or cross-project writes, or when you need the action attributed to a named service principal rather than the pipeline’s build service identity.
  • Both omitted: The agent has no ADO API access. Stage 3 still uses $(System.AccessToken) for write operations (sufficient for most same-project safe outputs).
# Agent can read ADO; executor writes via $(System.AccessToken) (default)
permissions:
read: my-read-sc
# Agent can read ADO; executor writes via named ARM identity
permissions:
read: my-read-sc
write: my-write-sc
# No ADO API read for agent; executor writes via named ARM identity
permissions:
write: my-write-sc