Back to Checks
aws

Cloud KMS key does not grant access to allUsers or allAuthenticatedUsers

kms_key_not_publicly_accessible
Service: kmsSeverity: critical
OfficialBuilt-inVerified
Categories:internet-exposedidentity-access
Resource Type:AwsKmsKey

KMS keys are assessed for excessive access in key policies or grants, including * principals and broadly scoped permissions to multiple identities.

Risk

Broad access to a KMS key enables unauthorized kms:Decrypt and data-key generation, breaking confidentiality. With admin rights, attackers can change policies or schedule deletion, undermining control integrity and threatening availability of data dependent on the key.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks kms_key_not_publicly_accessible

Recommendation

Apply least privilege to KMS keys:

  • Restrict principals to specific roles and accounts
  • Prefer narrow, time-bound grants
  • Separate key administration from usage
  • Use conditions to limit context
  • Review regularly and remove wildcard or cross-account exposure

Remediation

CLI

aws kms put-key-policy --key-id <example_resource_id> --policy-name default --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::<account_id>:root"},"Action":"kms:\*","Resource":"\*"}]}'

Terraform

# Restrict KMS key policy to the account root to avoid any public ("*") principals
data "aws_caller_identity" "current" {}

resource "aws_kms_key" "<example_resource_name>" {
  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" } # Critical: limit to account root to remove public access
        Action    = "kms:*"
        Resource  = "*"
      }
    ]
  })
}

NativeIaC

# CloudFormation: restrict KMS key policy to account root (removes any public access)
Resources:
  <example_resource_name>:
    Type: AWS::KMS::Key
    Properties:
      KeyPolicy:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: arn:aws:iam::<account_id>:root  # Critical: only account root can access; prevents public "*" principals
            Action: kms:*
            Resource: '*'

Other

1Open AWS Console > Key Management Service (KMS)
2Select the affected key and go to the Key policy tab
3Click Edit and remove any statement with Principal set to "\*" (or AWS: "\*")
4Ensure a statement exists that allows only arn:aws:iam::<account_id>:root
5Save changes

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.lib.policy import is_policy_public
from prowler.providers.aws.services.kms.kms_client import kms_client


class kms_key_not_publicly_accessible(Check):
    def execute(self):
        findings = []
        for key in kms_client.keys:
            if (
                key.manager == "CUSTOMER"
                and key.state == "Enabled"
                and key.policy is not None
            ):  # only customer KMS have policies
                report = Check_Report_AWS(metadata=self.metadata(), resource=key)
                report.status = "PASS"
                report.status_extended = f"KMS key {key.id} is not exposed to Public."
                # If the "Principal" element value is set to { "AWS": "*" } and the policy statement is not using any Condition clauses to filter the access, the selected AWS KMS master key is publicly accessible.
                if is_policy_public(
                    key.policy,
                    kms_client.audited_account,
                    not_allowed_actions=[],
                ):
                    report.status = "FAIL"
                    report.status_extended = (
                        f"KMS key {key.id} may be publicly accessible."
                    )
                findings.append(report)
        return findings