✨ The Containment Era is here. Secure AI workloads before they breach. →The Containment Era is here. →The Containment Era is here. →Explore ✨
Every runner is an open pipe. Until now.
When using the native egress path, every self-hosted GitHub Actions runner has unrestricted outbound internet access. No traffic logging. No destination policy. A compromised dependency inherits those permissions instantly. This architecture breaks that chain at the network layer — FQDN-based default-deny egress, zero bypass risk, full audit trail.
The CI/CD exfiltration trifecta. Leg three is the problem.
Runners hold secrets and credentials by design. They execute millions of lines of third-party code per build. When using the native egress path, they can reach any destination on the internet. The first two legs are features. The third is what turns compromise into breach — and it is the only one Aviatrix governs.
Dependency compromise
Poisoned package published to a public registry. Passes vulnerability scanning — no known CVE at install time. The March 2025 tj-actions compromise (23,000+ repositories) and the March 2026 TeamPCP Cascade (10,000+ CI/CD workflows) both entered this way.
Package install
npm install fetches the compromised package from the registry. The malicious code loads into the runner process alongside legitimate dependencies. No CVE exists at install time — vulnerability scanners pass it. The runner now executes attacker-controlled code with full access to the runner environment.
Credential harvest
Malicious code reads $GITHUB_TOKEN, AWS_ACCESS_KEY_ID, SSH keys, and Docker configs from environment variables. Constructs exfiltration payload. Indistinguishable from legitimate runner activity at the process layer.
Exfiltration attempt — blocked
Malicious code initiates outbound HTTPS to an attacker-controlled endpoint. TCP SYN traverses the Aviatrix Spoke Gateway. Destination is not in the WebGroup permit list. Connection never completes. Credentials have nowhere to go.
Audit trail
Blocked connection logged at the Spoke Gateway with runner identity, destination FQDN, policy rule name, and timestamp. Exportable to SIEM. CoPilot DCF Logs provides per-runner traffic analysis — full attribution for SOC 2, HIPAA, PCI-DSS, and FedRAMP audit requirements.
Two enforcement layers. Zero code changes.
Enforcement runs at the network infrastructure layer, outside the runner's trust boundary entirely. No agent to install. No process to kill. No bypass risk.
Spoke Gateway — network-level egress control
Deploy an Aviatrix Spoke Gateway into the VPC or VNET where self-hosted runners reside. The gateway automatically updates the subnet route table to point 0.0.0.0/0 to its network interface — runners immediately have no public IP and all egress flows through the gateway. Zero bypass risk: no software process on the runner can circumvent the route table. Every outbound connection is logged with source identity, destination IP, port, and timestamp.
Distributed Cloud Firewall — FQDN-based egress policy
Traffic passing through the Spoke Gateway is evaluated against FQDN-based WebGroup policies using Aviatrix DCF L7 filtering. SmartGroups match runner VMs by subnet or tag — Python runners allow PyPI, Node runners allow npm, Docker runners allow container registries. A three-tier evaluation model ensures nothing falls through: named permits first, per-runner-group rules second, default-deny at tier three. The default-deny is not a fallback; it is the posture. Every match is logged to CoPilot with a human-readable rule name, workload identity, destination FQDN, and timestamp.
Why static IPs don't solve this
Static IPs control where traffic comes from. They do nothing to control where traffic goes. A runner with a static IP can exfiltrate to evil.attacker.io:443 just as easily as one without. Static IPs let the enterprise set ingress allowlists on internal firewalls; they provide zero egress destination control. Aviatrix controls the destination — enforced and logged at the network layer.
Enforcement architecture
Private Subnet · VPC / VNET · Spoke Gateway · DCF enforcement · CoPilot audit
Three-tier evaluation. First match wins.
Every packet from every self-hosted runner traverses three tiers in order. Deploy all rules in monitor mode first; promote to enforcement rule by rule after validating against production traffic. The dataplane never reloads on rule changes.
Rules (examples)
| Tier | Role | Source | Destination | Action | Notes |
|---|---|---|---|---|---|
| 1 | Named permits | Runner subnet CIDR | Cloud service endpoints (CIDR) | PERMIT | ECR, ACR, blob storage. No-SNI traffic requires CIDR, not FQDN — cloud provider endpoints that don't present SNI must be matched by IP range. Evaluated first. |
| 2 | Per-runner-group rules | SmartGroup — subnet or tag match | WebGroup per runner profile | PERMIT | Python: pypi.org + github.com. Node: registry.npmjs.org + github.com. Docker: registries + github.com. Traffic not matching falls to Tier 3. |
| 3 | Default deny | Any runner | ANY | DENY + LOG | All protocols. Not a fallback — this is the posture. Must be configured as a default action rule, not a named policy entry. Every match logged to CoPilot DCF Logs. |
SmartGroup and WebGroup objects (examples)
| Object | Type | Purpose |
|---|---|---|
| runner-subnet-sg | Subnet SmartGroup | Matches the runner subnet CIDR in the VPC/VNET. Source identity for all egress rules. |
| wg-python-runners | FQDN WebGroup | Permits pypi.org, files.pythonhosted.org, github.com. Applied to Python runner SmartGroup. |
| wg-node-runners | FQDN WebGroup | Permits registry.npmjs.org, github.com. Applied to Node runner SmartGroup. |
| wg-docker-runners | FQDN WebGroup | Permits container registries and github.com. Applied to Docker runner SmartGroup. |
| wg-minimal | FQDN WebGroup | Permits github.com only. For restricted runner profiles with no external dependency fetch. |
What this architecture governs — and what it does not
Out of scope
Pre-execution code analysisSCA/SAST tools (Snyk, Socket, Dependabot) scan dependencies before code reaches the runner. Aviatrix governs runtime network access regardless of whether code was flagged.
Action hardeningReplacing untrusted third-party Actions with audited versions (e.g. Chainguard Actions) reduces execution risk. Aviatrix governs what any Action can reach on the network once it runs.
Out of scope
Content inspectionDomain-based, not content-based. Aviatrix controls whether a connection to a destination is permitted. What is sent over a permitted connection requires TLS inspection (available) as a separate control that can be enabled on a per-rule basis in DCF.
East-west pipeline trafficThis VCA governs external egress at the Spoke Gateway. Internal VPC traffic between pipeline services requires separate DCF policy scoped to internal SmartGroups.
Everything your team needs.
Reference Architecture
Prerequisites, SmartGroup and WebGroup design, full three-tier DCF policy pack, TLS decryption configuration, routing architecture, and known constraints. For platform engineers deploying the blueprint.
Download PDF →Threat Model & Enforcement
CI/CD exfiltration trifecta, full kill chain with point of intervention, three enforcement tiers, why static IPs don't solve this, architectural boundaries, and compliance evidence for SOC 2, HIPAA, PCI-DSS, FedRAMP, and NIST SSDF. For security architects.
Download PDF →Field & Buyer Overview
Threat narrative, architecture summary, three things your current stack can't do, compliance proof points, and discovery questions for security conversations. For security and platform teams evaluating the architecture.
Download PDF →Full Terraform Blueprint
Infrastructure as code for the complete deployment: Aviatrix Spoke Gateway, subnet routing, DCF WebGroup templates for Python, Node, Docker, and minimal egress profiles. One terraform apply, deploys in under 30 minutes.
Attack simulation
Lab recording. A compromised runner tries to post fake PII data to an external webhook website. The DCF default-deny rule fires before the TCP handshake completes. CoPilot DCF logs the attempt with full runner identity and rule attribution.
Available soonTrusted by enterprise security teams
SOC 2 Type II
Independently audited
ISO 27001
Certified
500+ enterprises
Including 10% of the Fortune 500
Zero data-plane access
Aviatrix never touches your traffic
Documented before you find them in production.
Lab-validated limitations and workarounds for the self-hosted runner architecture. Published upfront so your POC matches the docs.
Phase 1 covers self-hosted runners in VPC/VNET only
This VCA governs runners deployed as VMs in a private subnet. GitHub-hosted runners and Actions Runner Controller (ARC) on Kubernetes are not covered — see Phase 2 below.
TLS inspection requires explicit configuration
Domain-based blocking stops most exfiltration scenarios without TLS decryption. For environments requiring payload-level visibility on permitted connections, TLS termination at the Spoke Gateway is available but must be explicitly configured — it is not on by default.
Coming in Phase 2
Expanded runner coverage – ARC on Kubernetes and Github-hosted runner per-repository identity
Phase 2 extends enforcement to Actions Runner Controller pods on EKS and AKS as well as Github-hosted runners — SmartGroups keyed to namespace and label selectors, same zero bypass risk at the pod level. This phase also introduces per-repository VPN identity: each repository gets its own network identity so blast radius shrinks from "anything any repo needs" to "only what this specific repo needs." Both ship as Terraform reference modules.
The Terraform is built.
The policy pack is on GitHub.
Deploy an Aviatrix Spoke Gateway, apply the WebGroup templates, and go from ungoverned egress to default-deny in a single afternoon. Pick the path that matches where you are.
NEW TO AVIATRIX
Start with Enterprise — VCAs included free
Subscribe on AWS or Azure Marketplace, deploy Enterprise in under 15 minutes, then deploy this VCA on top. 30-day free trial — VCAs included.
Subscribe through AWS or Azure Marketplace · 30-day free trial · No contract
ALREADY ON ENTERPRISE
Pull the Terraform from GitHub
Full blueprint, WebGroup templates for Python, Node, Docker, and minimal egress profiles. Deploy in under 30 minutes. Destroy cleanly with one command.
Get the Terraform →1 managed network per VPC/VNET · No agent on runner · No code changes