Back to Checks
aws

Inline IAM policy does not allow kms:* privileges

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

IAM inline policies are analyzed to identify statements that grant unrestricted AWS KMS access via the wildcard action kms:*.

Risk

Granting kms:* enables decryption of protected data, modification of key policies and grants, and disabling or deleting keys.

Impacts:

  • Confidentiality via unauthorized decryption
  • Integrity through key/grant tampering
  • Availability if keys are disabled or deleted, breaking encrypted workloads

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks iam_inline_policy_no_full_access_to_kms

Recommendation

Replace kms:* with least-privilege, action-scoped permissions limited to required operations and specific key ARNs. Enforce separation of duties for key admins vs users. Prefer managed policies over inline and apply guardrails (permissions boundaries/SCPs). Add conditions to constrain service, region, and encryption context.

Remediation

Terraform

# Inline IAM policy without kms:* full access
resource "aws_iam_user_policy" "<example_resource_name>" {
  name = "<example_resource_name>-policy"
  user = "<example_resource_name>"

  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = [
        "kms:Encrypt" # CRITICAL: replace 'kms:*' with specific action(s) to remove full access
      ]
      Resource = "*"
    }]
  })
}

NativeIaC

# CloudFormation: Inline IAM policy without kms:* full access
Resources:
  <example_resource_name>:
    Type: AWS::IAM::User
    Properties:
      Policies:
        - PolicyName: <example_resource_name>-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - kms:Encrypt  # CRITICAL: replace 'kms:*' with only required KMS action(s) to remove full access
                Resource: "*"

Other

1In the AWS Console, open IAM and go to Users, Roles, or Groups (where the inline policy is attached)
2Select the entity, go to the Permissions tab, and open the inline policy that allows KMS
3Click Edit policy and switch to the JSON editor
4Replace any "Action": "kms:*" with only the specific KMS action(s) required (e.g., "kms:Encrypt")
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_full_service_access

critical_service = "kms"


class iam_inline_policy_no_full_access_to_kms(Check):
    def execute(self):
        findings = []

        for policy in iam_client.policies.values():
            if policy.type == "Inline":
                report = Check_Report_AWS(metadata=self.metadata(), resource=policy)
                report.region = iam_client.region
                report.resource_id = f"{policy.entity}/{policy.name}"
                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 '{critical_service}:*' privileges."

                if policy.document and check_full_service_access(
                    critical_service, policy.document
                ):
                    report.status = "FAIL"
                    report.status_extended = f"{policy.type} policy {policy.name}{' attached to ' + resource_type_str + ' ' + resource_attached if policy.attached else ''} allows '{critical_service}:*' privileges."

                findings.append(report)

        return findings