AID-I-002.001: Internal AI Network Segmentation

Version 1.20261015 · Actionable sub-technique

Implement network segmentation and microsegmentation strategies to isolate AI systems and their internal components (e.g., training environments, model serving endpoints, data stores, agent control planes) from general corporate networks and other critical IT/OT systems.

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).
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

Apply least privilege to *internal* network communications for AI systems.
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

Implement microsegmentation (SDN, service mesh, host-based firewalls) for fine-grained internal control.
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: 53

Action: 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

Separate development/testing environments from production using distinct accounts or projects.
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

Regularly review and audit internal network segmentation rules.
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

Commercial / hosted tools

Threat mappings

MITRE ATLAS

MAESTRO

OWASP LLM Top 10 2026

OWASP ML Top 10 2023

OWASP Top 10 for Agentic Applications 2026

NIST Adversarial Machine Learning 2025

Cisco Integrated AI Security and Safety Framework

Google Secure AI Framework 2.0 - Risks

Databricks AI Security Framework 3.0

AID-I-002.001: Internal AI Network Segmentation | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version