# EC2 Instance Has a Public IP -- Review If Needed

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

Source: https://zop.dev/integrations/aws/recommendations/ec2-instance-has-a-public-ip-review-if-needed
Updated: 2026-08-19

---

## 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](https://aws.amazon.com/vpc/pricing/). 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

```bash
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:

```bash
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.
