Back to Checks
IAM user does not have active access keys that have never been used
iam_user_no_setup_initial_access_key
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:identity-accesssecrets
Resource Type:AwsIamUser
IAM users with a console password and active access keys that have last_used as N/A are identified.
This highlights accounts where programmatic credentials exist but have never been exercised.
Risk
Active yet unused access keys expand the attack surface. If exposed, attackers gain programmatic access for unauthorized API calls, causing data exfiltration (confidentiality), unauthorized changes (integrity), and service disruption (availability). Dormant keys also bloat credential inventory, delaying detection and rotation.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks iam_user_no_setup_initial_access_keyRecommendation
Apply least privilege to programmatic access:
- Do not provision access keys by default for console users
- Prefer IAM roles and temporary credentials
- Require justification and time-bounded key creation
- Regularly review usage and disable/delete unused keys
- Limit to one active key per user and enforce rotation with monitoring
Remediation
CLI
aws iam delete-access-key --user-name <example_resource_name> --access-key-id <example_resource_id>Terraform
# Ensure IAM access key is not active
resource "aws_iam_access_key" "<example_resource_name>" {
user = "<example_resource_name>"
status = "Inactive" # Critical: disables the key so it isn't active and cannot be flagged as never used
}NativeIaC
# CloudFormation: ensure IAM access key is not active
Resources:
AccessKey:
Type: AWS::IAM::AccessKey
Properties:
UserName: "<example_resource_name>"
Status: Inactive # Critical: disables the key so it isn't active and cannot be flagged as never usedOther
1In the AWS Console, go to IAM > Users and select the user.
2Open the Security credentials tab.
3Under Access keys, find keys with Last used = N/A and Status = Active.
4Choose Deactivate or Delete for each such key.
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
class iam_user_no_setup_initial_access_key(Check):
def execute(self) -> Check_Report_AWS:
findings = []
for user_record in iam_client.credential_report:
if (
user_record["access_key_1_active"] == "true"
and user_record["access_key_1_last_used_date"] == "N/A"
and user_record["password_enabled"] == "true"
) or (
user_record["access_key_2_active"] == "true"
and user_record["access_key_2_last_used_date"] == "N/A"
and user_record["password_enabled"] == "true"
):
if (
user_record["access_key_1_active"] == "true"
and user_record["access_key_1_last_used_date"] == "N/A"
and user_record["password_enabled"] == "true"
):
self.add_finding(
user=user_record,
status="FAIL",
status_extended=f"User {user_record['user']} has never used access key 1.",
findings=findings,
)
if (
user_record["access_key_2_active"] == "true"
and user_record["access_key_2_last_used_date"] == "N/A"
and user_record["password_enabled"] == "true"
):
self.add_finding(
user=user_record,
status="FAIL",
status_extended=f"User {user_record['user']} has never used access key 2.",
findings=findings,
)
else:
self.add_finding(
user=user_record,
status="PASS",
status_extended=f"User {user_record['user']} does not have access keys or uses the access keys configured.",
findings=findings,
)
return findings
def add_finding(self, user, status, status_extended, findings):
report = Check_Report_AWS(metadata=self.metadata(), resource=user)
report.region = iam_client.region
report.resource_id = user["user"]
report.resource_arn = user["arn"]
report.status = status
report.status_extended = status_extended
# Search user in iam_client.users to get tags
for iam_user in iam_client.users:
if iam_user.arn == user["arn"]:
report.resource_tags = iam_user.tags
break
findings.append(report)