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
Reviewed
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 grants an implicit assumption right to every IAM identity in that account rather than to the root user specifically. IAM trust policy evaluation treats an account-level Principal as scoping the permission to the account boundary; the account’s own identity-based policies then 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 grants sts:AssumeRole on the target role 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, silently grants that developer role access to every root-scoped role in the account, including this one.

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.

{
  "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 that fails closed for anything else.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::123456789012:role/BreakGlassAdmin" },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": { "sts:ExternalId": "break-glass-2026" }
      }
    }
  ]
}

Before applying the change, capture the existing policy document so the correction is reversible:

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

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.
  • Ask a representative unrelated IAM identity in the account to attempt the same call and confirm it is denied with AccessDenied.
  • 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.

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.

After remediation

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

Discover more

Connected KBY resources