Back to Checks
aws

EC2 instance has no more than one Elastic Network Interface (ENI) attached

ec2_instance_uses_single_eni
Service: ec2Severity: low
OfficialBuilt-inVerified
Categories:trust-boundaries
Resource Type:AwsEc2Instance

EC2 instances are evaluated for attached network adapters. It identifies instances with more than one ENI-including efa, interface, or trunk types-and distinguishes those using a single adapter.

Risk

Multiple ENIs create dual-homed hosts across subnets and security groups, enabling unintended routing and policy bypass. Adversaries can pivot between segments, use alternate egress for data exfiltration, or exploit asymmetric paths, undermining segmentation and confidentiality/integrity while complicating containment.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks ec2_instance_uses_single_eni

Recommendation

Prefer a single ENI per instance.

If multi-homing is unavoidable:

  • Place ENIs in least-privilege subnets/SGs
  • Keep source/destination check enabled and routes explicit
  • Use gateways/LBs for NAT or ingress, not the host
  • Monitor flow logs and formally approve exceptions

Embed defense in depth and zero trust.

Remediation

CLI

aws ec2 detach-network-interface --attachment-id <ATTACHMENT_ID>

Terraform

# Terraform: instance with only the primary ENI
resource "aws_instance" "<example_resource_name>" {
  ami           = "<example_resource_id>"
  instance_type = "t3.micro"
  subnet_id     = "<example_resource_id>"  # FIX: only primary ENI; no additional network_interface attachments
}

NativeIaC

# CloudFormation: ensure the instance has only one ENI
Resources:
  <example_resource_name>:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: <example_resource_id>
      InstanceType: t3.micro
      SubnetId: <example_resource_id>  # FIX: creates a single primary ENI; do not add extra NetworkInterfaces/attachments

Other

1Open the AWS EC2 console and go to Network Interfaces
2Filter by the affected instance ID
3Select each non-primary network interface (Primary cannot be detached)
4Choose Actions > Detach
5Confirm the detach for each secondary ENI

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ec2.ec2_client import ec2_client


class ec2_instance_uses_single_eni(Check):
    def execute(self):
        findings = []
        for instance in ec2_client.instances:
            report = Check_Report_AWS(metadata=self.metadata(), resource=instance)
            eni_types = {"efa": [], "interface": [], "trunk": []}
            if not instance.network_interfaces:
                report.status = "PASS"
                report.status_extended = (
                    f"EC2 Instance {instance.id} has no network interfaces attached."
                )
            else:
                for eni_id in instance.network_interfaces:
                    if (
                        eni_id in ec2_client.network_interfaces
                        and ec2_client.network_interfaces[eni_id].type in eni_types
                    ):
                        eni_types[ec2_client.network_interfaces[eni_id].type].append(
                            eni_id
                        )

                message_status_extended = ""
                if (
                    len(eni_types["efa"])
                    + len(eni_types["interface"])
                    + len(eni_types["trunk"])
                    > 1
                ):
                    report.status = "FAIL"
                    message_status_extended = (
                        f"EC2 Instance {instance.id} uses multiple ENIs: ("
                    )
                else:
                    report.status = "PASS"
                    message_status_extended = (
                        f"EC2 Instance {instance.id} uses only one ENI: ("
                    )

                if eni_types["efa"]:
                    message_status_extended += f" EFAs: {eni_types['efa']}"
                if eni_types["interface"]:
                    message_status_extended += f" Interfaces: {eni_types['interface']}"
                if eni_types["trunk"]:
                    message_status_extended += f" Trunks: {eni_types['trunk']}"
                report.status_extended = message_status_extended + " )."

            findings.append(report)

        return findings