[IAM.4] IAM root user access key should not exist is a Critical AWS Security Hub CSPM control that fails while the account root user has any access key, active or inactive. To fix it, find what still signs requests with that key, move those workloads to IAM roles or IAM users, then deactivate and delete the key as root.
No server is involved: the work is a credential report, a CloudTrail search, a migration and a short root console session.
What the scanner is actually detecting
The finding comes from AWS Security Hub CSPM, a cloud security posture management tool; if that category is new to you, see what CSPM is and what it checks. The control is backed by an AWS Config managed rule, so the “asset” in the report is an AWS account ID, not a host.
| Field | Value |
|---|---|
| Control | [IAM.4] IAM root user access key should not exist |
| Severity | Critical |
| Resource type | AWS::::Account |
| AWS Config rule | iam-root-access-key-check |
| Schedule | Periodic |
| CIS AWS Foundations Benchmark | v5.0.0 1.3, v3.0.0 1.4, v1.4.0 1.4, v1.2.0 1.12 |
The Config rule is COMPLIANT only if the root user access key does not exist. It does not look at whether the key is active or when it was last used, so a key that is switched off still fails. CIS numbering depends on the benchmark version your standard uses.
Real-world risk, stated honestly
AWS strongly recommends against creating root access keys because the root user has full access to all AWS services and resources in the account, including billing. An access key is a long-term credential with no expiry date, and requests signed with it do not go through the console MFA prompt. If the secret leaks from a repository, a CI variable or an old ~/.aws/credentials file, whoever holds it can call any API in the account.
For proportion:
- A key that is inactive and whose secret nobody can find is a much smaller exposure than an active key used nightly by a script. It is still a finding, because reactivating it only needs a root console session.
- In AWS Organizations member accounts, a service control policy can restrict what the root user does. That limits damage, but it does not clear IAM.4.
- Replacing the key is only half the job. The role or IAM user that takes over should get only the permissions the workload needs, so also audit the replacement roles for excess permissions.
How to confirm it in your account
The first two checks work with ordinary IAM read credentials. You do not need root to confirm the finding.
Is a root key present?
aws iam get-account-summary --query "SummaryMap.AccountAccessKeysPresent"
A value of 1 means the root user has at least one access key.
Was it used, and for what? (credential report)
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 --decode > cred-report.csv
awk -F, '$2 ~ /:root$/ {print "key1 active="$9, "last_used="$11, $12, $13; print "key2 active="$14, "last_used="$16, $17, $18}' cred-report.csv
Repeat the generate command until it returns COMPLETE. The root row is the one whose ARN ends in :root. Columns 9 to 13 are access_key_1_active, last_rotated, last_used_date, last_used_region and last_used_service; columns 14 to 18 are the same for the second key. A last used value of N/A means the key was never used (or not since tracking began on April 22, 2015). IAM builds a new report at most once every four hours.
One trap: access_key_1_active is FALSE both when there is no key and when the key is inactive. If the report shows FALSE but IAM.4 still fails, an inactive key is almost certainly still there.
Who is calling with it? (CloudTrail)
Get the key ID from the Access keys section of the root user’s Security credentials page, then search CloudTrail event history in every enabled Region:
KEY=AKIAIOSFODNN7EXAMPLE
for r in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text); do
aws cloudtrail lookup-events --region "$r"
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue="$KEY"
--output json |
jq -r '.Events[].CloudTrailEvent | fromjson |
[.eventTime, .awsRegion, .eventSource, .eventName, .sourceIPAddress, .userAgent] | @tsv'
done
Event history covers only the last 90 days of management events in each Region, so a quarterly job or a data-event-only workload can be missed. For longer history, query your trail or CloudTrail Lake for events where userIdentity.type is Root and userIdentity.accessKeyId starts with AKIA. AKIA is the prefix for long-term access keys; root console sessions use temporary credentials, whose IDs start with ASIA. The sourceIPAddress and userAgent fields usually point straight at the server or tool that owns the key.
How to fix it
1. Move every consumer off the key
- Code on EC2, ECS or Lambda: attach an IAM role (instance profile, task role or execution role) and remove the static key from the configuration. The SDKs pick up role credentials automatically.
- Servers or tools outside AWS: create an IAM user or role scoped to exactly the actions seen in CloudTrail, and issue credentials for that identity instead.
- People using the root key with the CLI: give them an administrative identity in IAM Identity Center. For the rare root-only task done programmatically, AWS now recommends the aws login command with root credentials, which issues temporary credentials instead of a long-term key.
2. Deactivate, wait, then delete (standalone or management account)
Only the root user can do this. IAM users and roles cannot, whatever their permissions.
- Sign in to the AWS Management Console as the root user.
- In the upper right corner, choose your account name or number, then Security credentials.
- In Access keys, select the key, then under Actions choose Deactivate. Any request signed with it now fails with access denied.
- Leave it inactive long enough to cover your scheduled jobs, including month-end ones, and watch for failures.
- Return to the same page, choose Actions, Delete, enter the access key ID to confirm, and choose Delete.
The CLI equivalent, run with root credentials, is:
aws iam delete-access-key --access-key-id AKIAIOSFODNN7EXAMPLE
It prints nothing on success. AWS GovCloud (US) root keys follow a separate procedure in the GovCloud User Guide.
3. Member accounts with centralized root access
If centralized root access is enabled in AWS Organizations, the management account or the IAM delegated administrator can remove the key without signing in to the member’s root user. The console path is IAM, Root access management, select the account, Take privileged action, Delete root credentials. That option removes the root password, access keys and signing certificates and deactivates MFA. To remove only the access key, use a scoped session from the CLI (AssumeRoot needs a Regional STS endpoint, hence the Region flag):
creds=$(aws sts assume-root --region us-east-1
--target-principal 111122223333
--task-policy-arn arn=arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials
--duration-seconds 900 --query Credentials --output json)
export AWS_ACCESS_KEY_ID=$(echo "$creds" | jq -r .AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo "$creds" | jq -r .SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo "$creds" | jq -r .SessionToken)
aws iam list-access-keys
aws iam delete-access-key --access-key-id AKIAIOSFODNN7EXAMPLE
The IAMDeleteRootUserCredentials task policy allows listing, last-used lookups and deletion, but not deactivation, so finish the CloudTrail review before you start this session.
How to verify the fix and rescan
- Rerun aws iam get-account-summary –query “SummaryMap.AccountAccessKeysPresent” and confirm it returns 0.
- In a centralized root session, aws iam list-access-keys should return an empty list.
- Check the control state in Security Hub CSPM:
aws securityhub get-findings --filters '{"ComplianceSecurityControlId":[{"Value":"IAM.4","Comparison":"EQUALS"}],"RecordState":[{"Value":"ACTIVE","Comparison":"EQUALS"}]}'
--query "Findings[].[Compliance.Status,AwsAccountId,Region]" --output text
IAM.4 is a periodic control, and Security Hub CSPM runs periodic checks within 12 or 24 hours of the previous run. Expect the finding to stay FAILED for up to a day after the deletion before it flips to PASSED.
What can break and how to roll back
- During the deactivation window: any forgotten script, backup job or third-party tool gets access denied. Roll back by reactivating the key on the same Access keys page; the key ID and secret do not change, so nothing needs reconfiguring. Then migrate that consumer and deactivate again.
- After deletion: there is no undo. A deleted key cannot be restored, and creating a new root key would reopen the finding. The recovery path is to give the broken workload its own role or IAM user.
- Centralized “Delete root credentials”: this also removes the root password and MFA. If a member account later needs a root-only task, the management account can run Allow password recovery, and whoever controls the root email inbox can reset the password. Delete the credentials again when the task is done.
- Monitoring gaps: alerts keyed on the old key ID go quiet. Alert on any root activity instead, for example the GuardDuty finding type Policy:IAMUser/RootCredentialUsage.
Common false positive reasons
True false positives are rare, because the check is a simple existence test. What usually looks like one is:
- Deactivated, not deleted: the key still exists, so IAM.4 keeps failing. This is expected behavior.
- Deleted, still FAILED: the periodic check has not run since the change.
- Credential report says FALSE: the report cannot tell an inactive key from no key, as described above.
- The same account in several Regions: if Security Hub CSPM runs in several Regions, each can report IAM.4 for the same account. The root user is global, so one deletion clears every copy at the next check.
- “The key was never used”: a last used value of N/A lowers urgency and removes the migration step, but the finding is still valid.
FAQ
Is deactivating the root access key enough to pass IAM.4?
No. The rule is compliant only when no root access key exists. Deactivation is a safe intermediate step, not the fix.
Can an IAM administrator delete the root access key?
Not in a standalone or management account; AWS requires you to sign in as root. In member accounts with centralized root access, the management account or IAM delegated administrator can delete it through a privileged AssumeRoot session.
Does root MFA protect the access key?
No. MFA protects console sign-in. API requests signed with the access key never pass through the MFA prompt, which is why the key itself has to go.
Tracking this finding across many accounts
Across dozens of AWS accounts, the hard part is bookkeeping: which accounts still hold a root key, which are in the deactivate-and-wait window, and which consumers were migrated. SITEY is a self-hosted vulnerability management platform that imports findings from 16 scanners, merges duplicates per scanner (not across scanners), and uses AI triage to suggest false positives with evidence for a human to decide. Check whether your cloud posture tool is one of its supported imports before planning around it.
Sources
- AWS: Security Hub CSPM controls for IAM ([IAM.4])
- AWS IAM User Guide: Delete access keys for the root user
- AWS IAM User Guide: Generate credential reports for your AWS account
- AWS IAM User Guide: Perform a privileged task on an AWS Organizations member account
- AWS CloudTrail User Guide: CloudTrail userIdentity element