Back to Checks
aws

IAM inline policy does not allow privilege escalation

iam_inline_policy_allows_privilege_escalation
Service: iamSeverity: high
OfficialBuilt-inVerified
Categories:identity-accessprivilege-escalation
Resource Type:AwsIamPolicy

IAM inline policies are evaluated for permission combinations that enable privilege escalation, such as sts:AssumeRole, iam:PassRole, attaching/editing policies, or broad wildcards. The result highlights inline policies that allow a principal to obtain higher effective access.

Risk

Excessive inline policy permissions let identities escalate to admin, compromising CIA:

  • Confidentiality: read secrets and data
  • Integrity: alter policies, code, and configs
  • Availability: delete or stop resources, disable logging Attackers can persist by creating keys/users or assuming powerful roles.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks iam_inline_policy_allows_privilege_escalation

Recommendation

Apply least privilege and remove escalation paths:

  • Avoid wildcards and sensitive actions like sts:AssumeRole, iam:PassRole, or policy modification without tight scope
  • Restrict by resource and Condition
  • Prefer managed, versioned policies; use permissions boundaries/SCPs
  • Require reviews and MFA for admins

Remediation

Terraform

# Terraform: Replace the risky inline policy with least-privilege actions
resource "aws_iam_user_policy" "<example_resource_name>" {
  name = "<example_resource_name>"
  user = "<example_resource_name>"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = "ec2:DescribeInstances"  # FIX: only non-privilege-escalation action; remove IAM/STS escalation actions
      Resource = "*"                       # FIX: safe read-only scope
    }]
  })
}

NativeIaC

# CloudFormation: Replace the risky inline policy with least-privilege actions
Resources:
  <example_resource_name>:
    Type: AWS::IAM::UserPolicy
    Properties:
      UserName: <example_resource_name>
      PolicyName: <example_resource_name>
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action: ec2:DescribeInstances  # FIX: allow only non-privilege-escalation action; remove IAM/STS privilege-escalation actions
            Resource: "*"                  # FIX: no risky wildcard admin actions; this read-only action is safe

Other

1In the AWS Console, go to IAM > Users/Roles/Groups and select the entity with the failing inline policy
2In the Permissions tab, under Inline policies, choose the flagged policy and click Edit
3Remove privilege-escalation actions (e.g., iam:CreatePolicyVersion, iam:AttachUserPolicy, iam:PassRole, sts:AssumeRole, iam:UpdateAssumeRolePolicy)
4Keep only the minimum required, non-escalating permissions (for example, read-only actions)
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.privilege_escalation import (
    check_privilege_escalation,
)


class iam_inline_policy_allows_privilege_escalation(Check):
    def execute(self) -> Check_Report_AWS:
        findings = []

        for policy in iam_client.policies.values():
            if policy.type == "Inline":
                report = Check_Report_AWS(metadata=self.metadata(), resource=policy)
                report.resource_id = f"{policy.entity}/{policy.name}"
                report.region = iam_client.region
                report.status = "PASS"

                resource_type_str = report.resource_arn.split(":")[-1].split("/")[0]
                resource_attached = report.resource_arn.split("/")[-1]

                report.status_extended = f"{policy.type} policy {policy.name}{' attached to ' + resource_type_str + ' ' + resource_attached if policy.attached else ''} does not allow privilege escalation."

                policies_affected = check_privilege_escalation(
                    getattr(policy, "document", {})
                )

                if policies_affected:
                    report.status = "FAIL"

                    report.status_extended = (
                        f"{policy.type} policy {policy.name}{' attached to ' + resource_type_str + ' ' + resource_attached if policy.attached else ''} allows privilege escalation using the following actions: {policies_affected}".rstrip()
                        + "."
                    )

                findings.append(report)

        return findings