Back to Checks
Amazon EC2 launch template has no public IP addresses configured on network interfaces
ec2_launch_template_no_public_ip
Service: ec2Severity: high
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsEc2LaunchTemplate
EC2 launch templates with versions that either enable associate_public_ip_address for network interfaces or reference ENIs already associated with public IPs
Risk
Assigning public IPs makes instances Internet-reachable, enabling:
- Loss of confidentiality via unauthorized access and data exfiltration
- Compromised integrity through remote exploitation and tampering
- Reduced availability from DDoS and brute-force traffic Attackers can scan exposed services and pivot within the VPC.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks ec2_launch_template_no_public_ipRecommendation
Apply least privilege and network segmentation:
- Set
associate_public_ip_address=falsein launch templates - Avoid referencing ENIs with public IPs
- Place instances in private subnets behind NAT/ALB
- Use Session Manager, bastions, or VPC endpoints/PrivateLink for access Adopt defense in depth to minimize exposure.
Remediation
CLI
aws ec2 create-launch-template-version --launch-template-id <example_resource_id> --launch-template-data '{"NetworkInterfaces":[{"DeviceIndex":0,"AssociatePublicIpAddress":false}]}' --set-default-versionTerraform
# EC2 launch template configured to not assign public IPs
resource "aws_launch_template" "<example_resource_name>" {
name = "<example_resource_name>"
network_interfaces {
device_index = 0
associate_public_ip_address = false # Critical: disables public IP assignment on the primary ENI
}
}NativeIaC
# CloudFormation: Launch template configured to not assign public IPs
Resources:
<example_resource_name>:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
NetworkInterfaces:
- DeviceIndex: 0
AssociatePublicIpAddress: false # Critical: disables public IP assignment on the primary ENIOther
1Open the EC2 console and go to Launch Templates
2Select the template and choose Actions > Create new version
3Under Network settings > Advanced network configuration, set Auto-assign public IP to Disable
4Ensure no Network interface is attached that already has a public IP
5Check Set as default version and choose Create launch template version
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_launch_template_no_public_ip(Check):
def execute(self):
findings = []
for template in ec2_client.launch_templates:
report = Check_Report_AWS(metadata=self.metadata(), resource=template)
versions_with_autoassign_public_ip = []
versions_with_network_interfaces_public_ip = []
for version in template.versions:
# Check if the launch template version assigns a public IP address
if version.template_data.associate_public_ip_address:
versions_with_autoassign_public_ip.append(
str(version.version_number)
)
if version.template_data.network_interfaces:
for network_interface in version.template_data.network_interfaces:
if network_interface.public_ip_addresses:
versions_with_network_interfaces_public_ip.append(
str(version.version_number)
)
break
if (
versions_with_autoassign_public_ip
or versions_with_network_interfaces_public_ip
):
report.status = "FAIL"
if (
versions_with_autoassign_public_ip
and versions_with_network_interfaces_public_ip
):
report.status_extended = f"EC2 Launch Template {template.name} is configured to assign a public IP address to network interfaces upon launch in template versions: {', '.join(versions_with_autoassign_public_ip)} and is using a network interface with public IP addresses in template versions: {', '.join(versions_with_network_interfaces_public_ip)}."
elif versions_with_autoassign_public_ip:
report.status_extended = f"EC2 Launch Template {template.name} is configured to assign a public IP address to network interfaces upon launch in template versions: {', '.join(versions_with_autoassign_public_ip)}."
elif versions_with_network_interfaces_public_ip:
report.status_extended = f"EC2 Launch Template {template.name} is using a network interface with public IP addresses in template versions: {', '.join(versions_with_network_interfaces_public_ip)}."
else:
report.status = "PASS"
report.status_extended = f"EC2 Launch Template {template.name} is neither configured to assign a public IP address to network interfaces upon launch nor using a network interface with public IP addresses."
findings.append(report)
return findings