Back to blog
AWSBest PracticesCloud SecurityIdentity & AccessOperations & Compliance

Root Account In Use: Locking Down AWS Root Access

Active AWS root account usage is a top security risk. Learn how to detect root logins, harden root with MFA, block it with SCPs, and prevent drift.

TL;DR

This check flags any AWS account where the root user has signed in or made API calls in the last 90 days. The root account has unrestricted power and should sit idle behind hardware MFA. Lock it down, move daily work to IAM roles, and alert on every root login.

The AWS root account is the original identity created when you first open an account. It owns everything, can do anything, and cannot be restricted by IAM policies. That makes it the single most dangerous credential in your entire cloud footprint. When Lensix detects that this account has been used within the last 90 days, it is telling you that someone is operating with god-mode access for tasks that almost certainly do not require it.

This post explains what the check looks at, why active root usage is a serious risk, how to remediate it, and how to make sure it never drifts back.


What this check detects

The account_rootinuse check inspects your account's credential activity and reports whether the root user has been active in the past 90 days. It looks at two signals:

  • Console sign-ins by the root user, visible in CloudTrail as ConsoleLogin events with a root user identity.
  • API or CLI activity authenticated with root credentials or root access keys.

The simplest source of truth is the IAM credential report, which records the last time root signed in to the console and the last time a root access key was used.

Note: The root account is identified in CloudTrail by userIdentity.type set to Root. Unlike IAM users and roles, root activity has no associated IAM policy, which is exactly why it bypasses every guardrail you have built.

You can pull the same data the check relies on with the AWS CLI:

aws iam generate-credential-report

aws iam get-credential-report \
  --query 'Content' --output text | base64 -d | \
  grep '<root_account>'

The root row reports password_last_used, access_key_1_last_used_date, and whether MFA is active. If any of those timestamps fall inside the last 90 days, this check fails.


Why it matters

Root is not just another admin account. It can perform actions that no IAM principal can, including closing the account, changing the account email and root password, restoring an IAM policy that has locked everyone out, and changing your AWS support plan. Because it ignores IAM, none of your carefully scoped permission boundaries or service control policies apply to it.

Active root usage matters for a few concrete reasons:

  • No least privilege. Every root action runs with unlimited authority. A typo or a malicious command has no blast radius limit.
  • Weak auditability. When several people share root, you lose attribution. CloudTrail tells you root did something, not which engineer.
  • Long-lived access keys. Root access keys are a classic breach vector. If one leaks in a repo, CI log, or laptop backup, an attacker owns the account completely.
  • Compliance failures. CIS AWS Foundations, PCI DSS, SOC 2, and most internal frameworks explicitly require that root is not used for routine operations and that it carries MFA.

The 2019 breach pattern that hit several startups followed the same script: a root access key committed to a public repository, discovered within minutes by automated scrapers, then used to spin up crypto-mining fleets and run up six-figure bills before anyone noticed.

Danger: If root access keys exist at all, treat them as a live incident. There is almost no legitimate reason to have them, and they cannot be scoped down. Delete them as the first step of remediation.


How to fix it

Remediation has two goals: stop using root for daily work, and harden root so a compromise becomes very hard. Work through these steps in order.

1. Find out what root was actually doing

Before you change anything, understand the activity that triggered this check. Query CloudTrail for recent root events:

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=root \
  --start-time "$(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --query 'Events[].{Time:EventTime,Event:EventName,Source:EventSource}' \
  --output table

Most of the time this reveals a console login for some task that could have been done with an IAM role, such as updating billing settings or fixing a misconfigured policy.

2. Delete any root access keys

Root should never have programmatic credentials. Check for them in the IAM console under My Security Credentials, or via the credential report you generated earlier. If keys exist, delete them. There is no CLI command an IAM user can run to delete root's keys, so you must sign in as root one final time to remove them through the console:

  1. Sign in as root.
  2. Open Account name → Security credentials.
  3. Under Access keys, deactivate then delete each key.

Warning: Before deleting a root access key, confirm nothing depends on it. Old automation, legacy backup tools, or forgotten scripts occasionally use root keys. Grep your IaC and CI configs for the key ID, and search CloudTrail for its accessKeyId to be sure.

3. Enable MFA on root

Root must have multi-factor authentication, ideally a hardware security key (FIDO2) or a dedicated hardware TOTP device stored in a safe, not a phone that an employee carries.

  1. Sign in as root.
  2. Go to Security credentials.
  3. Under Multi-factor authentication (MFA), choose Assign MFA device.
  4. Register a hardware key or hardware TOTP device.

4. Set a strong, stored root password

Rotate the root password to a long, randomly generated value and store it in a corporate password manager or secrets vault with strict access controls. Pair it with a distribution list email, not a personal one, so the account does not become unrecoverable when someone leaves.

5. Create a break-glass IAM role for the work you were doing as root

Whatever task pushed someone to root probably maps to an IAM action. Provision an admin role with MFA-enforced assumption so the team has a sanctioned path that is not root:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:root" },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": { "aws:MultiFactorAuthPresent": "true" },
        "NumericLessThan": { "aws:MultiFactorAuthAge": "3600" }
      }
    }
  ]
}

Note: A small set of tasks genuinely require root, including changing the account email, restoring a deleted root recovery option, and some support plan changes. AWS keeps a current list in its documentation. For everything else, use IAM.


How to prevent it from happening again

Hardening root once is not enough. Without monitoring and policy, someone will sign in as root again in three months. Build these controls so the check stays green on its own.

Alert on every root login

Set up an EventBridge rule that fires on any root console sign-in or API call and routes it to SNS, Slack, or your incident tool. Treat each alert as something to investigate, not noise.

{
  "source": ["aws.signin"],
  "detail-type": ["AWS Console Sign In via CloudTrail"],
  "detail": {
    "userIdentity": { "type": ["Root"] }
  }
}

Wire it to a notification target with the AWS CLI:

aws events put-rule \
  --name root-login-alert \
  --event-pattern file://root-login-pattern.json

aws events put-targets \
  --rule root-login-alert \
  --targets "Id"="1","Arn"="arn:aws:sns:us-east-1:111122223333:security-alerts"

Block root usage with a service control policy

If you run AWS Organizations, an SCP can deny almost all actions to the root principal in member accounts, leaving only the handful of operations that genuinely require it. This is the strongest preventive control available.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyRootUser",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringLike": { "aws:PrincipalArn": "arn:aws:iam::*:root" }
      }
    }
  ]
}

Warning: SCPs do not apply to the management account's own root user, and a blanket deny can lock you out of legitimate root-only tasks in member accounts. Test in a non-production OU first, and keep a documented break-glass procedure for the rare cases that need root.

Gate it in CI/CD with policy as code

Catch root access keys and missing MFA before they ever reach an account. A simple pipeline step using the credential report turns this into a hard gate:

#!/usr/bin/env bash
set -euo pipefail

aws iam generate-credential-report > /dev/null
report=$(aws iam get-credential-report --query 'Content' --output text | base64 -d)
root=$(echo "$report" | grep '<root_account>')

if echo "$root" | cut -d',' -f9 | grep -q 'true'; then
  echo "FAIL: root has active access keys"; exit 1
fi

if echo "$root" | cut -d',' -f8 | grep -q 'false'; then
  echo "FAIL: root MFA is not enabled"; exit 1
fi

echo "PASS: root is hardened"

Tip: Run this check on a schedule as well as in the pipeline. A nightly Lambda that reads the credential report and posts to Slack will catch drift that a one-time deploy gate misses, since root state can change without any infrastructure change.


Best practices

  • Treat root as break-glass only. The healthy state is an account whose root user has not logged in for months.
  • Use hardware MFA. A FIDO2 key resists phishing in ways that SMS and app-based codes do not.
  • Own root with a shared mailbox. Tie the account email to a monitored distribution list so departures do not orphan the account.
  • Never create root access keys. If you find one, treat it as an incident, not a cleanup task.
  • Centralize identity. Move humans onto IAM Identity Center (SSO) with short-lived role sessions, so root is irrelevant to daily work.
  • Document the exceptions. Keep a short runbook listing the few tasks that need root, who can perform them, and how each access is logged and reviewed.
  • Review the credential report monthly. It is the cheapest, fastest way to confirm root and your IAM users stay clean.

Active root usage is one of those findings that looks minor until the day it is not. Hardening it costs an hour and removes the most catastrophic single point of failure in your AWS account. Lock root in a glass case, watch the case, and do all of your real work with scoped, auditable identities.