AWS Security Hub · KMS
KMS.2: Decrypt is granted on all KMS keys
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub KMS.2 check?
KMS.2 fails when an IAM principal has an inline policy allowing kms:Decrypt or kms:ReEncryptFrom on all keys (Resource: "*") rather than on specific key ARNs. The control inspects inline policies attached to users, groups, and roles.
Why does KMS.2 matter?
Decrypt on "*" means a single compromised principal can decrypt anything in the account that any key protects. In the 2019 Capital One breach the second act was exactly this: the compromised role's broad kms:Decrypt let the attacker get AWS to decrypt 100M+ records for them. Scoping the action to the handful of keys a workload actually uses stops a stolen credential from unlocking the whole estate.
How do I fix KMS.2?
- Inventory inline policies and flag kms:Decrypt or kms:ReEncryptFrom paired with Resource: "*".
- Determine which keys each principal genuinely uses from CloudTrail.
- Rewrite the Resource element to list those specific key ARNs.
- Where an exact ARN list is impractical, scope the Resource element itself (for example a Region- and account-bound key ARN pattern like arn:aws:kms:us-east-1:111122223333:key/*) rather than relying on a Condition block, because KMS.2 only evaluates the Resource element and ignores the Condition element, so condition keys such as kms:ViaService will not clear the finding.
Remediation script · bash
# Stop the irreversible clock first: cancel any scheduled deletion, then re-enable.
for k in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
state=$(aws kms describe-key --key-id "$k" \
--query 'KeyMetadata.KeyState' --output text)
if [ "$state" = "PendingDeletion" ]; then
aws kms cancel-key-deletion --key-id "$k"
aws kms enable-key --key-id "$k" # cancel leaves it Disabled
echo "$k: deletion cancelled and re-enabled"
fi
done
# Turn rotation on for eligible customer-managed symmetric keys.
for k in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
read -r mgr spec <<<"$(aws kms describe-key --key-id "$k" \
--query 'KeyMetadata.[KeyManager,KeySpec]' --output text)"
if [ "$mgr" = "CUSTOMER" ] && [ "$spec" = "SYMMETRIC_DEFAULT" ]; then
aws kms enable-key-rotation --key-id "$k"
fi
done Full walkthrough (console steps, edge cases and verification) in the lesson Manage KMS encryption keys.
Is KMS.2 a false positive?
KMS.2 inspects only the Resource element and disregards the Condition block, so an inline policy that pairs kms:Decrypt on Resource "*" with a tight condition (kms:ViaService limiting use to a single service like S3 or RDS, an encryption-context constraint, or aws:PrincipalOrgID) still fails despite being effectively scoped. That construction is legitimate when the workload's key ARNs aren't fixed at authoring time, such as per-tenant keys or keys other accounts create, and a wildcard Resource behind a sharp Condition is the documented way to keep the grant least-privilege. When the conditions genuinely bound the access, record a suppression citing the condition keys instead of forcing in an ARN list, but verify the conditions actually narrow the grant first, because the control will keep flagging it regardless.