Skip to main content
cd ../config-traps
risk/register/account-root-principal-iam-trust-policy-grants-every-identity.html
AWS IAM Trust Policieshigh severityAmazon Web Services

Account Root Principal in IAM Trust Policy Grants Every Identity, Not Just Root

Severity
high
Generated
11 Aug 2026
Remediation
~20 minutes
Overview

A trust policy that names the account root ARN as Principal looks tightly scoped. It isn't: any IAM identity in the account with an sts:AssumeRole grant can use it.

Operational summary

At a glance

Symptom
An engineering team discovers, usually through a CloudTrail review or an access audit, that an IAM role intended for a single break-glass administrator can…
Likely cause
Specifying an AWS account, whether by account ID or root ARN, as a trust policy Principal grants an implicit assumption right to every IAM…
Impact
The blast radius is every permission attached to the assumed role, reachable by any current or future IAM identity in the account that acquires an sts:AssumeRole grant on…
Verification signal
Validation must show the role can still be assumed by every legitimate caller and can no longer be assumed by anyone else.Re-run aws iam get-role and confirm Principal…
Safe correction
Replace the account-root Principal with the specific IAM role or user ARNs that should be permitted to assume the role, and add a Condition that fails closed for…
Rollback or recovery
Rollback restores the previously captured trust policy document if the corrected policy blocks a legitimate workload.aws iam update-assume-role-policy --role-name ROLE_NAME --policy-document file://original-trust-policy.jsonStop condition: if any legitimate automated workload…

Symptom

An engineering team discovers, usually through a CloudTrail review or an access audit, that an IAM role intended for a single break-glass administrator can be assumed by dozens of unrelated IAM users and roles inside the same AWS account. The role’s trust policy looks deliberately narrow: it names only the account’s root ARN as the allowed Principal, and nobody on the team recalls granting anything broader. The role has never been touched since it was created, yet CloudTrail shows AssumeRole calls from service roles that have nothing to do with break-glass access.

False Assumption

The team assumed that naming the account root ARN (arn:aws:iam::ACCOUNT_ID:root) as the trust policy’s Principal restricts role assumption to the AWS account’s literal root user credentials, behaving like a single named identity. Under that assumption, only someone signed in as root, or explicitly delegated by root, could call sts:AssumeRole against the role.

Root Cause

Specifying an AWS account, whether by account ID or root ARN, as a trust policy Principal does not name the root user specifically. It delegates the assumption decision to the account’s own IAM policies. The trust policy by itself grants no identity access; the account’s identity-based policies decide which specific IAM users and roles are actually permitted to call sts:AssumeRole against that role’s ARN. Any IAM identity in the account whose identity-based policy allows sts:AssumeRole on the target role (for example, through Resource * or AdministratorAccess) can assume it, regardless of whether that identity policy existed before or after the trust policy was written, and without any further change to the trust policy itself.

Impact

The blast radius is every permission attached to the assumed role, reachable by any current or future IAM identity in the account that acquires an sts:AssumeRole grant on it, without triggering a further trust policy change or a security review. In practice this converts what looks like a tightly scoped, break-glass role into an account-wide privilege escalation path: an administrator who later attaches a broad sts:AssumeRole statement to an unrelated developer role, for a reason that has nothing to do with this trap, can let that developer role assume any role in the account whose trust policy names the account root, including this one, provided the statement’s Resource matches the target role (for example *).

Diagnosis

Confirm the pattern before changing anything. Retrieve the role’s current trust policy and check whether Principal references the account ARN or account ID rather than specific user or role ARNs.

aws iam get-role 
  --role-name ROLE_NAME 
  --query 'Role.AssumeRolePolicyDocument' 
  --output json

Expected evidence: a Statement.Principal.AWS value equal to arn:aws:iam::ACCOUNT_ID:root or the bare account ID, with no Condition block restricting the calling principal, for example no aws:PrincipalArn or sts:ExternalId condition. Cross-reference CloudTrail AssumeRole events for that role ARN over the widest available retention window to establish which principals have actually exercised the grant; this is what turns the finding from theoretical into material. Write down every legitimate caller found, including automated callers and service roles, because the corrected policy must list each of them.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::123456789012:root" },
      "Action": "sts:AssumeRole"
    }
  ]
}

Correction

Replace the account-root Principal with the specific IAM role or user ARNs that should be permitted to assume the role, and add a Condition such as an MFA requirement (callers must then assume the role with an MFA-authenticated session). Automated callers that cannot present MFA will be denied by that condition, so decide for each caller from the CloudTrail review whether it belongs in the list and whether it needs a separate statement. The intended break-glass principal must itself be in the Principal list and be able to satisfy MFA. Save the corrected document as corrected-trust-policy.json. Also audit identity-based policies that allow sts:AssumeRole broadly.

In the example below, the ARNs are placeholders for your actual intended callers. Each principal must exist when the policy is saved, otherwise the update is rejected. Do not name the role being edited as its own caller.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:role/PLACEHOLDER_INTENDED_CALLER_1",
          "arn:aws:iam::123456789012:user/PLACEHOLDER_INTENDED_CALLER_2"
        ]
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": { "aws:MultiFactorAuthPresent": "true" }
      }
    }
  ]
}

First capture the existing policy document so the correction is reversible, and check that the file is non-empty and contains the trust policy:

aws iam get-role --role-name ROLE_NAME 
  --query 'Role.AssumeRolePolicyDocument' 
  --output json > original-trust-policy.json

Do not run update-assume-role-policy until original-trust-policy.json exists and has been checked.

Before applying the change, confirm that every legitimate caller from the CloudTrail review appears in the new Principal list, and test the change first on a comparable role in a non-production account. Verify that the break-glass principal is in the list and can assume the role with MFA. Also confirm that someone with IAM permissions that do not depend on this role (for example another admin role or the root user) can run the rollback if needed. Then apply the corrected document:

aws iam update-assume-role-policy 
  --role-name ROLE_NAME 
  --policy-document file://corrected-trust-policy.json

Validation

Validation must show the role can still be assumed by every legitimate caller and can no longer be assumed by anyone else.

  • Re-run aws iam get-role and confirm Principal now lists only the intended ARNs and the Condition block is present.
  • Ask each legitimate caller to run aws sts assume-role --role-arn ROLE_ARN --role-session-name validation-test from their own credentials and confirm success.
  • Choose a test identity in the account whose identity-based policy allows sts:AssumeRole on the role, but which is not in the Principal list, and have it attempt the same call. Confirm it is denied with AccessDenied, which shows the trust policy is the control.
  • Monitor CloudTrail AssumeRole events for the role ARN for at least one full business cycle after the change to confirm no unexpected principal successfully calls it.

Rollback

Rollback restores the previously captured trust policy document if the corrected policy blocks a legitimate workload. It must be run by an identity with IAM permissions that does not rely on assuming this role.

aws iam update-assume-role-policy 
  --role-name ROLE_NAME 
  --policy-document file://original-trust-policy.json

Stop condition: if any legitimate automated workload fails to assume the role within the validation window, or an on-call escalation reports blocked access, apply the rollback command immediately and re-open diagnosis before reattempting the correction with an updated Principal or Condition list.

Prevention

Add an automated check, for example an IAM Access Analyzer custom check or a CI guard on Terraform or CloudFormation IAM role definitions, that flags any trust policy Principal equal to an account ID or root ARN without an accompanying Condition. Treat that pattern as a required manual security review gate rather than an accepted default. Record in the account’s IAM baseline which roles are intentionally account-wide, if any, versus which were assumed to be root-only by mistake, and review that list on the same cadence as other least-privilege reviews described in the AWS Well-Architected Security Pillar’s design principles.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

arn:aws:iam::ACCOUNT_ID:root
sts:AssumeRole
aws iam get-role 
  --role-name ROLE_NAME 
  --query 'Role.AssumeRolePolicyDocument' 
  --output json
04

Verify, roll back or escalate

Verify

Validation must show the role can still be assumed by every legitimate caller and can no longer be assumed by anyone else.Re-run aws iam get-role and confirm Principal now lists only the intended ARNs and the Condition block is present.Ask…

Rollback

Rollback restores the previously captured trust policy document if the corrected policy blocks a legitimate workload.aws iam update-assume-role-policy --role-name ROLE_NAME --policy-document file://original-trust-policy.jsonStop condition: if any legitimate automated workload fails to assume the role within the validation window, or…

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

The KBY Brief

Fixed? Get the next one before it hits you: The KBY Brief

Practical fixes for the systems you run, by email about twice a week. Unsubscribe at any time.

About this page

Dates

Published

Last updated

Corrections

  • : Corrected during a review of published articles. Details

Was this useful?

Reports go to the site owner and are used to correct pages. Corrections are listed at /corrections.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources