AID-I-002.001: Internal AI Network Segmentation
Internal Communication Controls
Enforces strict internal communication rules through firewalls, security groups, and network policies to limit lateral movement and reduce the internal blast radius of a compromise.
Agent Backend Isolation
This also isolates high-privilege agent backends (e.g. orchestration layers with access to credentials, vector DBs, or model registries) from lower-trust, user-facing inference frontends, so that a compromised public-facing agent cannot laterally move into data-rich components.
A2A applicability: The measured internal reachability population includes every agent-to-agent gateway or listener, broker topic or queue, direct peer edge, discovery-advertised endpoint, callback, and relay crossing an internal trust-zone boundary. Apply the allow/deny graph to authenticated workload identities and exact peer routes, not only user-facing service ports.
Pillars: infra
Lifecycle: building, operation
Scope boundary
Owns segmentation and measured reachability among organization-controlled internal AI components, trust zones, environments, agent listeners, broker topics, and peer routes. It does not govern connections to remote third-party, SaaS, or cross-organization services.
AID-I-002.002: AID-I-002.001 segments internal organization-controlled networks and components; AID-I-002.002 governs connections from the AI system to external services and cross-organization agent endpoints. Classify the path by the destination trust and administrative boundary, not merely by whether the endpoint uses a private address or encrypted transport.
Implementation guidance
- AID-I-002.001-G001: Host critical AI components on dedicated network segments (VLANs, VPCs).
- AID-I-002.001-G002: Apply least privilege to *internal* network communications for AI systems.
- AID-I-002.001-G003: Implement microsegmentation (SDN, service mesh, host-based firewalls) for fine-grained internal control.
- AID-I-002.001-G004: Separate development/testing environments from production using distinct accounts or projects.
- AID-I-002.001-G005: Regularly review and audit internal network segmentation rules.
AID-I-002.001-G001
Concept:
This is 'macro-segmentation'. By placing different environments (e.g., training, inference, data storage) in separate virtual networks, you create strong, high-level boundaries. A compromise in one segment, like a data science experimentation VPC, is prevented at the network level from accessing the production inference VPC.
Define Separate VPCs with Infrastructure as Code
Use a tool like Terraform to define distinct, non-overlapping Virtual Private Clouds (VPCs) for each environment. This ensures the separation is deliberate, version-controlled, and reproducible.
# File: infrastructure/networks.tf (Terraform)
# VPC for the production AI inference service
resource "aws_vpc" "prod_vpc" {
cidr_block = "10.0.0.0/16"
tags = { Name = "aidefend-prod-vpc" }
}
# A completely separate VPC for the AI model training environment
resource "aws_vpc" "training_vpc" {
cidr_block = "10.1.0.0/16"
tags = { Name = "aidefend-training-vpc" }
}
# A VPC for the data science team's sandboxed experimentation
resource "aws_vpc" "sandbox_vpc" {
cidr_block = "10.2.0.0/16"
tags = { Name = "aidefend-sandbox-vpc" }
}
# By default, these VPCs cannot communicate with each other.
# Any connection (e.g., VPC Peering) must be explicitly defined and secured.Action: Provision separate, dedicated VPCs for your production, staging, and development/training environments. Do not allow VPC peering between them by default. All promotion of artifacts (like models) between environments should happen through a secure, audited CI/CD pipeline that connects to registries, not by direct network access between the VPCs.
Verify every indirect path
Reconcile the intended segment graph with peering, transit gateways, VPNs, NAT, service endpoints, shared DNS/resolvers, load balancers, proxies, package mirrors, and cloud-control-plane permissions in every applicable account and region. Test that a workload cannot create or alter one of those paths with its own identity. A direct VPC separation result is insufficient when an allowed mediator can relay traffic onward.
AID-I-002.001-G002
Concept:
Within a VPC, use firewall rules (like Security Groups in AWS) to enforce least-privilege access between components. A resource should only be able to receive traffic on the specific ports and from the specific internal sources it absolutely needs to function. All other traffic should be denied.
Create Fine-Grained Security Group Rules
This Terraform example defines two security groups. The first is for a model inference server, which only allows traffic on port 8080 from the second security group, which is attached to an internal API gateway. This prevents anyone else, including other services in the same VPC, from directly accessing the model. Terraform removes the provider-created allow-all egress rule when it creates a security group. Keep inline ingress and egress arguments absent, and express every intended flow through standalone rule resources so one resource model owns the rules.
# File: infrastructure/security_groups.tf
# A release gate verifies network-policy.auto.tfvars.json and its Sigstore
# bundle before Terraform starts. Every variable below is required; none has a default.
variable "vpc_id" {
type = string
}
variable "inference_service_port" {
type = number
validation {
condition = (
floor(var.inference_service_port) == var.inference_service_port
&& var.inference_service_port >= 1
&& var.inference_service_port <= 65535
)
error_message = "signed inference service port must be a valid TCP port"
}
}
variable "network_policy_version" {
type = string
validation {
condition = length(trimspace(var.network_policy_version)) > 0
error_message = "signed network policy version is required"
}
}
variable "network_policy_sha256" {
type = string
validation {
condition = can(regex("^sha256:[0-9a-f]{64}$", var.network_policy_sha256))
error_message = "signed network policy digest must be canonical SHA-256"
}
}
data "aws_vpc" "prod_vpc" {
id = var.vpc_id
}
resource "aws_security_group" "internal_api_gateway_sg" {
name_prefix = "internal-api-gateway-sg-"
vpc_id = data.aws_vpc.prod_vpc.id
tags = {
Name = "internal-api-gateway-sg"
AidefendPolicyVersion = var.network_policy_version
AidefendPolicySHA256 = var.network_policy_sha256
}
}
resource "aws_security_group" "inference_sg" {
name_prefix = "inference-server-sg-"
vpc_id = data.aws_vpc.prod_vpc.id
tags = {
Name = "inference-server-sg"
AidefendPolicyVersion = var.network_policy_version
AidefendPolicySHA256 = var.network_policy_sha256
}
}
resource "aws_vpc_security_group_ingress_rule" "gateway_to_inference" {
security_group_id = aws_security_group.inference_sg.id
referenced_security_group_id = aws_security_group.internal_api_gateway_sg.id
description = "Policy-bound inference port from internal gateway"
from_port = var.inference_service_port
to_port = var.inference_service_port
ip_protocol = "tcp"
}
resource "aws_vpc_security_group_egress_rule" "gateway_to_inference" {
security_group_id = aws_security_group.internal_api_gateway_sg.id
referenced_security_group_id = aws_security_group.inference_sg.id
description = "Policy-bound gateway egress to inference"
from_port = var.inference_service_port
to_port = var.inference_service_port
ip_protocol = "tcp"
}Action: For each component of your AI system, create a dedicated security group. Define ingress rules that only allow traffic from the specific security groups of the internal services that need to connect to it. Keep inline ingress/egress arguments absent and define only required flows with standalone aws_vpc_security_group_*_rule resources. Terraform removes the AWS default allow-all egress rule when creating these groups; independently read back both groups and fail the release if any undeclared rule exists.
Bind the rules to the workloads that actually run
The Terraform resources above are not deployment evidence until the release gate reads the current compute, load-balancer, task, or pod inventory and proves that every intended gateway interface is attached to internal_api_gateway_sg, every intended inference interface is attached to inference_sg, and no extra security group restores a broader path. Bind that attachment inventory, region/account, VPC, rule IDs, policy digest, and readback time into one result. From the actual gateway workload, require a successful TCP probe to the inference service on the signed port; from an unlisted workload require denial on that port, and from the gateway require denial to unlisted ports, IPv4/IPv6 destinations, and indirect proxy or load-balancer paths. Missing attachment inventory or a probe that did not originate from the measured workload is INSUFFICIENT_DATA, not PASS.
AID-I-002.001-G003
Concept:
Microsegmentation provides fine-grained, identity-aware traffic control between individual workloads (e.g., pods in Kubernetes). Even if two pods are on the same network segment, they cannot communicate unless an explicit policy allows it. This requires a baseline 'default-deny' policy to be effective.
Implement Kubernetes NetworkPolicies (with Default Deny)
First, apply a default-deny policy to the namespace. Then, create specific 'allow' policies for required traffic.
# File: k8s/default-deny-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: ai-production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# File: k8s/allow-gateway-to-inference.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-gateway-to-inference
namespace: ai-production
spec:
podSelector:
matchLabels:
app: model-server
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
---
# Source egress is evaluated independently from destination ingress.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-gateway-egress-to-inference
namespace: ai-production
spec:
podSelector:
matchLabels:
app: api-gateway
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: model-server
ports:
- protocol: TCP
port: 8080
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Action: Deploy a CNI plugin that supports NetworkPolicy enforcement (e.g., Calico, Cilium). Implement a 'default-deny-all' policy for each namespace containing AI workloads. Then, create specific, least-privilege policies to allow only the necessary communication paths between pods. Confirm your CNI (Calico, Cilium, etc.) is actually enforcing NetworkPolicy. Vanilla kube-proxy alone doesn't block traffic; without enforcement this policy is only documentation.
Verify effective Kubernetes identity and paths
Bind the applied policy to the exact namespace UID, workload controller UID/generation, pod labels, service account, service/endpoints, CNI implementation/version, and policy readback observed for the release. Prove the required gateway-to-model TCP path and DNS resolution from a selected gateway pod, then prove denial from an unmatched pod, to an unlisted port, across an unlisted namespace, and over both IPv4 and IPv6 where enabled. Enumerate required control-plane and service-mesh sidecar paths in the signed environment policy instead of silently exempting them. hostNetwork pods or a CNI mode that does not enforce the selected policy remain INSUFFICIENT_DATA unless a separately verified host/network enforcement path covers them.
AID-I-002.001-G004
Concept:
This is a fundamental security control that isolates volatile development or sandbox environments from the stable, hardened production environment using strong administrative boundaries provided by cloud providers. The control must be directional and explicit: prevent production accounts from creating or accepting peering with development VPCs, and attach a reciprocal policy to the development/sandbox OU so those accounts cannot create or accept peering with production VPCs.
Implement a Multi-Account/Multi-Project Cloud Strategy with SCPs
Structure your cloud organization and apply Service Control Policies (SCPs in AWS, Organization Policies in GCP, Azure Policy) to enforce separation. In AWS, VPC peering condition keys are ARN-valued ec2:AccepterVpc and ec2:RequesterVpc; do not use nonexistent *VpcInfo/OwnerId keys.
# Version-controlled AWS account and OU registry
My-AI-Organization/ (Root)
|-- OU: AI-Prod
| +-- Account: 111111111111 (AI-Prod)
+-- OU: AI-NonProd
|-- Account: 222222222222 (AI-Staging)
+-- Account: 333333333333 (AI-Dev/Sandbox)
# SCP A: attach to AI-Prod OU.
# Blocks prod accounts from creating peering to dev/sandbox VPCs and from
# accepting peering requested by dev/sandbox VPCs.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyProdCreatesPeeringToNonProdVpc",
"Effect": "Deny",
"Action": "ec2:CreateVpcPeeringConnection",
"Resource": "*",
"Condition": {
"ArnLike": {
"ec2:AccepterVpc": [
"arn:aws:ec2:*:222222222222:vpc/*",
"arn:aws:ec2:*:333333333333:vpc/*"
]
}
}
},
{
"Sid": "DenyProdAcceptsPeeringFromNonProdVpc",
"Effect": "Deny",
"Action": "ec2:AcceptVpcPeeringConnection",
"Resource": "*",
"Condition": {
"ArnLike": {
"ec2:RequesterVpc": [
"arn:aws:ec2:*:222222222222:vpc/*",
"arn:aws:ec2:*:333333333333:vpc/*"
]
}
}
}
]
}
# SCP B: attach the reciprocal policy to AI-NonProd OU, replacing the account
# list above with production VPC ARNs under account 111111111111.
Action: Maintain a version-controlled environment-to-account/VPC ARN registry and generate reciprocal organization policies from it. Deny direct network paths between production and non-production by default, including VPC peering, VPN, Transit Gateway attachments, and equivalent cloud constructs. Add AWS Config/EventBridge or CSPM detection for existing peering and indirect routes so legacy paths do not survive as silent exceptions.
Read back organization attachment and indirect-path state
For each in-scope production and non-production account, resolve its current organization root and OU ancestry, list the SCPs attached at every applicable level, retrieve the exact policy documents, and verify that the generated reciprocal deny statements are present under the intended current policy version. Reconcile that account/VPC registry with current peering, Transit Gateway, VPN, shared-network, private-endpoint, proxy/broker, identity-assumption, and artifact-promotion routes in each applicable region. Management-account and service-linked-role limitations must be reported explicitly. Stage a permitted artifact-promotion test and denied direct/indirect network tests before broad rollout, retaining rollback evidence. This is scoped to the environment's applicable route classes; it does not require every organization to deploy every named AWS feature.
AID-I-002.001-G005
Required authoritative inputs
Run this method after every network-policy change and on the freshness schedule in the signed audit policy. Do not rely on a weekly timer as the control. A separately credentialed inventory service must paginate every governed account/project, region, VPC/VNet, interface, security-group/NSG rule, prefix list, referenced group, route, gateway, attachment, private endpoint, resolver path, Kubernetes policy, and relevant IPv4/IPv6 flow. It signs a snapshot with the exact expected and observed population roots. Unsupported or unenumerated providers are INSUFFICIENT_DATA, not clean.
Normalized least-privilege graph auditor
# File: audits/segmentation_graph_audit.py
from __future__ import annotations
import hashlib
import json
import re
from dataclasses import dataclass
from typing import Callable
@dataclass(frozen=True, order=True)
class NetworkEdge:
source_asset: str
destination_asset: str
protocol: str
from_port: int
to_port: int
address_family: str
enforcement_point: str
@dataclass(frozen=True)
class VerifiedSegmentationPolicy:
policy_sha256: str
scope_id: str
expected_accounts: frozenset[str]
expected_regions: frozenset[str]
allowed_edges: frozenset[NetworkEdge]
required_edges: frozenset[NetworkEdge]
forbidden_path_classes: frozenset[str]
@dataclass(frozen=True)
class VerifiedNetworkSnapshot:
snapshot_sha256: str
scope_id: str
accounts: frozenset[str]
regions: frozenset[str]
observed_edges: frozenset[NetworkEdge]
unresolved_edges: frozenset[str]
asset_population_sha256: str
path_population_sha256: str
@dataclass(frozen=True)
class ReachabilityVerifier:
"""Required authenticated runtime adapter callables; no fallback implementation."""
verify: Callable[[VerifiedSegmentationPolicy, VerifiedNetworkSnapshot], dict[str, object]]
@dataclass(frozen=True)
class EvidenceWriter:
"""Required authenticated runtime adapter callables; no fallback implementation."""
append_and_verify: Callable[[dict[str, object]], dict[str, str]]
SHA256 = re.compile(r"^[0-9a-f]{64}$")
def append_verified(
evidence: EvidenceWriter, event: dict[str, object],
) -> dict[str, str]:
body = json.dumps(
event, sort_keys=True, separators=(",", ":"), allow_nan=False,
).encode("utf-8")
expected = hashlib.sha256(body).hexdigest()
receipt = evidence.append_and_verify(event)
if (
not isinstance(receipt, dict)
or set(receipt) != {
"event_sha256", "receipt_sha256", "writer_identity",
}
or receipt.get("event_sha256") != expected
or SHA256.fullmatch(str(receipt.get("receipt_sha256"))) is None
or not receipt.get("writer_identity")
):
raise OSError("segmentation evidence readback is absent or misbound")
return receipt
def audit(
*,
policy: VerifiedSegmentationPolicy,
snapshot: VerifiedNetworkSnapshot,
reachability: ReachabilityVerifier,
evidence: EvidenceWriter,
) -> dict[str, object]:
if snapshot.scope_id != policy.scope_id:
raise PermissionError("snapshot scope mismatch")
missing_accounts = policy.expected_accounts - snapshot.accounts
missing_regions = policy.expected_regions - snapshot.regions
if missing_accounts or missing_regions or snapshot.unresolved_edges:
event = {
"schema_version": "aidefend.segmentation-audit.v1",
"control": "AID-I-002.001",
"scope_id": policy.scope_id,
"policy_sha256": policy.policy_sha256,
"snapshot_sha256": snapshot.snapshot_sha256,
"missing_accounts": sorted(missing_accounts),
"missing_regions": sorted(missing_regions),
"unresolved_edges": sorted(snapshot.unresolved_edges),
"outcome": "INSUFFICIENT_DATA",
}
return {
"outcome": "INSUFFICIENT_DATA",
"evidence": append_verified(evidence, event),
}
if not policy.required_edges.issubset(policy.allowed_edges):
raise ValueError("required edges must be a subset of allowed edges")
extra = snapshot.observed_edges - policy.allowed_edges
missing = policy.required_edges - snapshot.observed_edges
replay = reachability.verify(policy=policy, snapshot=snapshot)
replay_fields = {
"outcome", "policy_sha256", "snapshot_sha256",
"population_sha256", "tested_forbidden_path_classes", "receipt_sha256",
}
if not isinstance(replay, dict) or set(replay) != replay_fields:
raise PermissionError("reachability receipt schema differs")
if (
replay.get("policy_sha256") != policy.policy_sha256
or replay.get("snapshot_sha256") != snapshot.snapshot_sha256
or replay.get("population_sha256") != snapshot.path_population_sha256
or set(replay.get("tested_forbidden_path_classes", []))
!= policy.forbidden_path_classes
or SHA256.fullmatch(str(replay.get("receipt_sha256"))) is None
):
raise PermissionError("reachability result is absent or misbound")
if replay.get("outcome") not in {"PASS", "FAIL"}:
raise RuntimeError("reachability verifier returned no closed outcome")
outcome = "FAIL" if extra or missing or replay["outcome"] == "FAIL" else "PASS"
event = {
"schema_version": "aidefend.segmentation-audit.v1",
"control": "AID-I-002.001",
"scope_id": policy.scope_id,
"policy_sha256": policy.policy_sha256,
"snapshot_sha256": snapshot.snapshot_sha256,
"asset_population_sha256": snapshot.asset_population_sha256,
"path_population_sha256": snapshot.path_population_sha256,
"extra_edges": [edge.__dict__ for edge in sorted(extra)],
"missing_edges": [edge.__dict__ for edge in sorted(missing)],
"reachability_receipt_sha256": replay["receipt_sha256"],
"outcome": outcome,
}
return {"outcome": outcome, "evidence": append_verified(evidence, event)}
Adapter and verification requirements
The provider adapter expands CIDRs, IPv6 ranges, prefix lists, protocol -1, port ranges, referenced groups, transitive routes, peering, Transit Gateway, VPN, endpoints, shared networks, and load-balancer targets into normalized edges without silently discarding unknown forms. The policy adapter verifies issuer, audience, signature, monotonic version, scope, expected account/region set, exception expiry, graph digest, and the distinction between permitted edges and policy-required positive paths before constructing VerifiedSegmentationPolicy. The reachability verifier uses read-only credentials distinct from the policy writer and combines provider reachability analysis with active positive and negative probes from the exact source identities.
Open-source tools
- iptables
- nftables
- firewalld
- Kubernetes
- Istio
- Linkerd
- Kuma
- Project Calico
- Cilium
- AWS CLI v2
- Azure CLI
- OpenTofu
- Ansible Core
- Pulumi
Commercial / hosted tools
- Illumio Segmentation
- Akamai Guardicore Segmentation
- Cisco Secure Workload
- Amazon EC2 security groups
- Azure network security groups
- Google Cloud VPC firewall rules
- Tetrate Service Bridge
- Gloo Mesh
- AWS CloudFormation
- Google Cloud CLI
Threat mappings
MITRE ATLAS
- AML.T0044 Full AI Model Access (limits internal access)
- AML.T0036 Data from Information Repositories (limits internal access)
- AML.T0075 Enterprise Resource Discovery (segmentation limits which systems and services a compromised AI component can enumerate)
- AML.T0122 Exploitation of Remote Services (segmentation limits which internal AI services are reachable from a compromised workload)
MAESTRO
- Lateral Movement (Cross-Layer)
- Compromised RAG Pipelines (L2) (isolating internal DB access)
- Data Leakage (Cross-Layer)
OWASP LLM Top 10 2026
- LLM03:2026 Excessive Agency (microsegmentation limits the internal reach of a compromised agent)
OWASP ML Top 10 2023
- ML05:2023 Model Theft (limits internal access to model artifacts)
OWASP Top 10 for Agentic Applications 2026
- ASI03:2026 Identity and Privilege Abuse (network segmentation enforces access boundaries)
- ASI10:2026 Rogue Agents (internal segmentation contains rogue agent lateral movement)
- ASI07:2026 Insecure Inter-Agent Communication
- ASI08:2026 Cascading Failures (network segmentation limits cascade propagation)
NIST Adversarial Machine Learning 2025
- NISTAML.039 Compromising connected resources
- NISTAML.031 Model Extraction (internal segmentation limits extraction paths)
Cisco Integrated AI Security and Safety Framework
- AISubtech-14.1.2 Insufficient Access Controls (internal network and environment boundaries constrain access to AI infrastructure)
- AISubtech-8.2.3 Data Exfiltration via Agent Tooling (internal segmentation restricts data reach and unauthorized agent transport paths)
- AISubtech-9.1.2 Unauthorized or Unsolicited System Access (internal agent routes and privileged backends are isolated by measured reachability)
- AISubtech-9.1.3 Unauthorized or Unsolicited Network Access (internal agent routes and privileged backends are isolated by measured reachability)
- AITech-14.1 Unauthorized Access (internal network and environment boundaries constrain access to AI infrastructure)
- AITech-8.2 Data Exfiltration / Exposure (internal segmentation restricts data reach and unauthorized agent transport paths)
Google Secure AI Framework 2.0 - Risks
- MXF: Model Exfiltration (internal segmentation limits model theft paths)
- RA: Rogue Actions (internal segmentation contains rogue agent lateral movement)
Databricks AI Security Framework 3.0
- Model 7.2: Model assets leak (internal segmentation restricts access to model assets)
- Platform 12.4: Unauthorized privileged access (internal segmentation enforces privilege boundaries)
- Agents - Core 13.13: Rogue Agents in Multi-Agent Systems (internal segmentation contains rogue agents)
- Agents - Core 13.3: Privilege Compromise (segmentation limits privilege escalation scope)