Back to Checks
aws

EC2 instance is not internet-facing with an instance profile attached

ec2_instance_internet_facing_with_instance_profile
Service: ec2Severity: high
OfficialBuilt-inVerified
Categories:internet-exposedidentity-access
Resource Type:AwsEc2Instance

EC2 instances with a public IP address and an attached instance profile (IAM role) are identified.

Instances lacking public exposure or without an instance profile are excluded.

Risk

Publicly reachable instances with IAM role credentials expand the blast radius. Remote exploits or misconfigurations can steal credentials via the instance metadata service, enabling unauthorized API calls, data exfiltration, and lateral movement, impacting confidentiality, integrity, and availability.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks ec2_instance_internet_facing_with_instance_profile

Recommendation

Avoid direct Internet exposure. Place workloads behind an Application Load Balancer and protect HTTP apps with WAF. Remove public IPs or restrict ingress to trusted sources. Apply least privilege to instance profiles and enforce IMDSv2. Use bastion hosts or Session Manager for admin access.

Remediation

CLI

aws ec2 disassociate-iam-instance-profile --association-id <ASSOCIATION_ID>

Terraform

# EC2 instance without a public IP to avoid being internet-facing
resource "aws_instance" "<example_resource_name>" {
  ami           = "<example_ami_id>"
  instance_type = "t3.micro"
  associate_public_ip_address = false  # Critical: disables public IPv4 so the instance is not internet-facing
}

NativeIaC

# CloudFormation: EC2 instance without a public IP to avoid being internet-facing
Resources:
  <example_resource_name>:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: <example_ami_id>
      InstanceType: t3.micro
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: <example_resource_id>
          AssociatePublicIpAddress: false  # Critical: disables public IPv4 so the instance is not internet-facing

Other

1In the AWS Console, go to EC2 > Instances and select the instance
2Choose Actions > Security > Modify IAM role
3Set IAM role to None and click Update IAM role
4Verify the instance no longer lists an IAM role (instance profile)
5Alternative (if you need the role): remove internet exposure
6Select the instance > Networking tab
7If an Elastic IP is attached, choose Disassociate Elastic IP
8For auto-assigned public IPv4, stop the instance and relaunch without a public IP or in a subnet without auto-assign public IPv4

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_internet_facing_with_instance_profile(Check):
    def execute(self):
        findings = []
        for instance in ec2_client.instances:
            if instance.state != "terminated":
                report = Check_Report_AWS(metadata=self.metadata(), resource=instance)
                report.status = "PASS"
                report.status_extended = f"EC2 Instance {instance.id} is not internet facing with an instance profile."
                if instance.public_ip and instance.instance_profile:
                    report.status = "FAIL"
                    report.status_extended = f"EC2 Instance {instance.id} at IP {instance.public_ip} is internet-facing with Instance Profile {instance.instance_profile['Arn']}."

                findings.append(report)

        return findings