EC2 instances with a public IPv4 address
What does ZopNight detect here?
AWS bills every in-use public IPv4 address at roughly $3.65 a month, and a public IP also puts the instance directly on the internet. ZopNight flags running instances that have one so you can confirm the exposure is intentional rather than inherited from a subnet default.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-153 |
| Category | compliance |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | ec2_public_ip.go |
Where it applies
Two different problems, one finding
A public IPv4 costs money: around $3.65 per address per month, since AWS began charging for every in-use address in 2024. On a fleet of a few hundred instances that is real, and it is invisible because it never appears as its own line item.
The larger issue is exposure. An instance with a public IP is reachable from the internet subject only to its security group, and security groups drift. Most instances that have one never needed one. They inherited it from a subnet configured to auto-assign.
This is a review prompt, not a defect
The rule is categorised compliance, not idle, and it deliberately reports no dollar saving.
Plenty of instances legitimately hold a public IP: bastion hosts, NAT instances, and anything
serving traffic directly. The finding asks a question rather than asserting waste.
It only fires on instances in the running state, and reads the discoverer’s public_ip
metadata flag rather than inferring exposure from tags.
Finding public IPs and MapPublicIpOnLaunch
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query 'Reservations[].Instances[?PublicIpAddress!=null].[InstanceId,PublicIpAddress,SubnetId]'Then check whether the subnet auto-assigns:
aws ec2 describe-subnets --subnet-ids subnet-0123456789abcdef0 --query 'Subnets[].MapPublicIpOnLaunch'If that returns true, every instance launched there gets a public IP whether or not it needs
one, which is usually the actual root cause rather than any individual instance.
How to fix it
Move the instance to a private subnet and route outbound traffic through a NAT Gateway or VPC endpoints. If it genuinely needs inbound internet access, put an ALB in front of it in a public subnet rather than exposing the instance. If the public IP is intentional (bastion, NAT, public endpoint), nothing needs doing, and marking the finding as accepted stops it resurfacing.