Back to Checks
aws

Unattached customer managed IAM policy does not allow '*:*' administrative privileges

iam_customer_unattached_policy_no_administrative_privileges
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:AwsIamPolicy

Customer-managed IAM policies that are unattached are evaluated for statements granting full administrative access using *:* wildcards.

The focus is on policies whose documents include unrestricted actions on all resources.

Risk

An unattached policy with *:* can be attached accidentally or maliciously, granting account-wide control. Attackers could read sensitive data (confidentiality), alter or delete resources (integrity), and disrupt services (availability), enabling rapid privilege escalation and lateral movement.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks iam_customer_unattached_policy_no_administrative_privileges

Recommendation

Remove or redesign these policies to enforce least privilege:

  • Avoid * in actions/resources; scope precisely and use conditions
  • Apply permissions boundaries and SCPs as guardrails
  • Require peer review and policy validation before attachment
  • Use analysis tools to refine permissions and delete unused policies

Remediation

CLI

aws iam create-policy-version --policy-arn <example_resource_arn> --set-as-default --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"iam:GetAccountSummary","Resource":"*"}]}'

Terraform

# IAM policy without '*:*' administrative privileges
resource "aws_iam_policy" "<example_resource_name>" {
  name   = "<example_resource_name>"
  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = "iam:GetAccountSummary"   # Critical: specific action, not '*'
        Resource = "*"                        # Critical: avoids '*:*' admin privileges
      }
    ]
  })
}

NativeIaC

# CloudFormation: managed policy without administrative '*:*' privileges
Resources:
  <example_resource_name>:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action: iam:GetAccountSummary  # Critical: use a specific action instead of '*'
            Resource: "*"                 # Critical: combined with specific action, avoids '*:*'

Other

1In the AWS Console, go to IAM > Policies
2Find the unattached customer managed policy and choose it
3Click Edit policy > JSON
4Remove any statement that allows Action "*" on Resource "*", or replace it with a specific action (e.g., "iam:GetAccountSummary")
5Save changes

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.iam_client import iam_client
from prowler.providers.aws.services.iam.lib.policy import check_admin_access


class iam_customer_unattached_policy_no_administrative_privileges(Check):
    def execute(self) -> Check_Report_AWS:
        findings = []
        for policy in iam_client.policies.values():
            # Check only for cutomer unattached policies
            if not policy.attached and policy.type == "Custom":
                report = Check_Report_AWS(metadata=self.metadata(), resource=policy)
                report.region = iam_client.region
                report.status = "PASS"
                report.status_extended = f"{policy.type} policy {policy.name} is unattached and does not allow '*:*' administrative privileges."
                if policy.document:
                    if check_admin_access(policy.document):
                        report.status = "FAIL"
                        report.status_extended = f"{policy.type} policy {policy.name} is unattached and allows '*:*' administrative privileges."
                findings.append(report)
        return findings