Back to Checks
aws

AWS account root user has not been used in the last day

iam_avoid_root_usage
Service: iamSeverity: high
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:AwsIamUser

AWS IAM root user activity is assessed by inspecting last-used timestamps for the root password and access keys. The finding indicates when the root identity has been used recently for console or programmatic access.

Risk

Recent root usage expands blast radius:

  • Data exfiltration (confidentiality)
  • Policy/key tampering (integrity)
  • Resource deletion and billing changes (availability) Routine use reduces anomaly visibility and eases account takeover impact.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks iam_avoid_root_usage

Recommendation

Minimize root usage by applying least privilege with admin roles or federated SSO and temporary credentials.

  • Enforce MFA on root
  • Avoid or remove root access keys
  • Require multi-person approval
  • Monitor and alert on any root sign-in
  • Use org guardrails for defense in depth

Remediation

Other

1Sign in to the AWS Management Console as the root user
2In the top-right, click your account name > Security credentials
3Under Access keys for the root user, delete all existing keys
4Sign out of the root user and do not use it again
5Wait 24 hours (until the root user has not been accessed for a full day) for the check to pass

Check Code

import datetime

import pytz
from dateutil import parser

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.iam_client import iam_client

maximum_access_days = 1


class iam_avoid_root_usage(Check):
    def execute(self) -> Check_Report_AWS:
        findings = []
        response = iam_client.credential_report

        for user in response:
            if user["user"] == "<root_account>":
                report = Check_Report_AWS(metadata=self.metadata(), resource=user)
                report.region = iam_client.region
                report.resource_id = user["user"]
                report.resource_arn = user["arn"]
                if (
                    user["password_last_used"] != "no_information"
                    or user["access_key_1_last_used_date"] != "N/A"
                    or user["access_key_2_last_used_date"] != "N/A"
                ):
                    if user["password_last_used"] != "no_information":
                        days_since_accessed = (
                            datetime.datetime.now(pytz.utc)
                            - parser.parse(user["password_last_used"])
                        ).days
                    elif user["access_key_1_last_used_date"] != "N/A":
                        days_since_accessed = (
                            datetime.datetime.now(pytz.utc)
                            - parser.parse(user["access_key_1_last_used_date"])
                        ).days
                    elif user["access_key_2_last_used_date"] != "N/A":
                        days_since_accessed = (
                            datetime.datetime.now(pytz.utc)
                            - parser.parse(user["access_key_2_last_used_date"])
                        ).days
                    if maximum_access_days >= days_since_accessed:
                        report.status = "FAIL"
                        report.status_extended = f"Root user in the account was last accessed {days_since_accessed} days ago."
                    else:
                        report.status = "PASS"
                        report.status_extended = f"Root user in the account wasn't accessed in the last {maximum_access_days} days."
                else:
                    report.status = "PASS"
                    report.status_extended = f"Root user in the account wasn't accessed in the last {maximum_access_days} days."
                findings.append(report)

        return findings