Back to Checks
aws

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

iam_customer_attached_policy_no_administrative_privileges
Service: iamSeverity: high
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:AwsIamPolicy

Attached customer-managed IAM policies are evaluated for statements granting full admin access via Action: "*", Resource: "*", i.e., *:*. Only policies you created and attached to identities are considered.

Risk

Unrestricted admin access lets any attached principal perform any action on any resource, enabling data exfiltration, policy tampering, credential creation, logging disablement, and destructive deletions-compromising confidentiality, integrity, and availability across the account.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks iam_customer_attached_policy_no_administrative_privileges

Recommendation

Enforce least privilege: replace wildcards with specific actions, scope Resource to needed ARNs, and add restrictive Conditions. Prefer role-based access and separation of duties. Use permissions boundaries and organization guardrails, and regularly review policies with policy validation and Access Analyzer.

Remediation

CLI

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

Terraform

# Terraform: Managed policy without '*:*' admin privileges
resource "aws_iam_policy" "<example_resource_name>" {
  name   = "<example_resource_name>"
  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = "iam:GetUser"  # CRITICAL: not "*" or "*:*"; removes admin privileges
      Resource = "*"             # CRITICAL: paired with specific action to avoid full admin
    }]
  })
}

NativeIaC

# CloudFormation: Replace admin '*' access with a specific action
Resources:
  <example_resource_name>:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action: iam:GetUser  # CRITICAL: removes '*:*' by allowing only a specific action
            Resource: "*"        # CRITICAL: no full admin since Action is not '*'

Other

1In the AWS Console, go to IAM > Policies and open the customer managed policy from the finding
2Select the Policy versions tab and click Create version
3Replace the JSON with:
4{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"iam:GetUser","Resource":"*"}]}
5Check Set as default version and click Create version
6Confirm the policy no longer contains an Allow with Action "*" (or "*:*") over Resource "*"

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_attached_policy_no_administrative_privileges(Check):
    def execute(self) -> Check_Report_AWS:
        findings = []
        for policy in iam_client.policies.values():
            # Check only for attached custom policies
            if 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 attached but 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 attached and allows '*:*' administrative privileges."
                findings.append(report)
        return findings