AWS Security Hub · IAM
IAM.21: Wildcard permissions grant far more access than intended
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub IAM.21 check?
IAM.21 fails when a customer-managed IAM policy grants service-level wildcard actions (an Allow on a pattern like service:*) rather than the specific actions a principal needs.
Why does IAM.21 matter?
service:* quietly grants every action that service will ever add, including destructive and privilege-escalating ones the workload never uses. A compromised role with such a grant becomes far more dangerous than its day job suggests: when attackers seized the Code Spaces AWS control panel in 2014, the breadth of access let them mass-delete EBS snapshots, S3 buckets, and AMIs and end the company. Narrowing to real usage means a stolen credential can do only what the workload genuinely does.
How do I fix IAM.21?
- Find policies containing service:* Allow statements across your customer-managed policies.
- Use IAM Access Analyzer policy generation plus CloudTrail to enumerate the actions each role actually invokes.
- Replace the wildcard with the concrete action list and roll it out, watching for access-denied errors.
- Add a guardrail (Config rule or CI policy lint) so new wildcard grants are caught before they ship.
Remediation script · bash
# Generate a least-privilege policy from real usage, then promote it to default.
aws accessanalyzer start-policy-generation \
--policy-generation-details principalArn=arn:aws:iam::123456789012:role/DataPipelineWorker
aws iam create-policy-version \
--policy-arn arn:aws:iam::123456789012:policy/DataPipelineWorkerPolicy \
--policy-document file://generated-policy.json --set-as-default
# Move a user's direct policy to a group: attach + add BEFORE detach, so there is no gap.
aws iam attach-group-policy --group-name developers \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam add-user-to-group --group-name developers --user-name nina
aws iam detach-user-policy --user-name nina \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# Detach a broad CloudShell grant, then scope down anyone with a genuine need.
aws iam detach-group-policy --group-name developers \
--policy-arn arn:aws:iam::aws:policy/AWSCloudShellFullAccess Full walkthrough (console steps, edge cases and verification) in the lesson Enforce IAM least privilege.
Is IAM.21 a false positive?
A few roles legitimately need the full action set of one service (a break-glass administrator, a security-audit role, or a backup/DR automation that must reach every operation a service exposes) and for those a service:* grant on a tightly scoped, well-monitored policy can be the intended design rather than a mistake. The control only evaluates customer-managed identity-based policies, so the same breadth delivered through an AWS-managed policy (for example a job-function policy) won't trip it, which means a FAILED finding sometimes just reflects that you wrote the grant yourself rather than that the grant is wrong. When the wildcard is deliberate, keep the blast radius small with a permissions boundary or resource and condition constraints, then record a Security Hub exception explaining why narrowing the action list isn't appropriate; don't fragment a genuine admin role into a brittle hand-maintained action list just to clear the check.
More IAM controls
- IAM.1 A policy grants full "*" administrative privileges
- IAM.2 Policies attached directly to users do not scale or audit cleanly
- IAM.3 Long-lived access keys have not been rotated
- IAM.4 The root user still has long-lived access keys
- IAM.5 Console users without MFA are one phish from compromise
- IAM.6 The root user is not protected by hardware MFA
- IAM.7 The IAM password policy is too weak
- IAM.8 Unused IAM keys and passwords are waiting to be leaked
- IAM.9 The root user can sign in without MFA
- IAM.10 IAM user password policies should be strong (PCI DSS)
- IAM.19 MFA should be enabled for all IAM users
- IAM.22 IAM credentials unused for 45 days should be removed