Skip to main content
cd ../config-traps
risk/register/trust-policies-with-wildcard-root-arns-skip-externalid.html
AWS Identitycritical severityAWS IAM

Trust Policies With Wildcard Root ARNs Skip ExternalId

Severity
critical
Reviewed
21 Jul 2026
Remediation
~20 minutes
Overview

A cross-account role in AWS IAM trusts arn:aws:iam::*:root without an sts:ExternalId condition, letting any AWS account call sts:AssumeRole successfully. CloudTrail shows a valid, authenticated call, so GuardDuty and standard IAM reviews rarely flag the session as anomalous until data has already moved.

Operational summary

At a glance

Symptom
Any external AWS account calls sts:AssumeRole against the role ARN and receives valid temporary credentials.
Likely cause
A cross-account role trust policy sets Principal to arn:aws:iam::*:root with no sts:ExternalId condition on AssumeRole.
Impact
Any AWS account on the internet can assume the role and inherit its attached permissions, logged as a normal authenticated call.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Scope the principal to the exact trusted account ARN and require a unique sts:ExternalId condition, verified via IAM Access Analyzer findings.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

A cross-account IAM role’s trust policy specifies "Principal": {"AWS": "arn:aws:iam::*:root"} for the sts:AssumeRole action, with no Condition block enforcing sts:ExternalId. IAM’s policy engine treats the wildcard root ARN as a syntactically valid principal, so the role deploys without error and passes automated linting tools that only check for the literal string "*" rather than wildcarded ARN patterns.

The Default State

This pattern appears constantly in SaaS onboarding runbooks and internal Terraform modules copied from vendor documentation. Engineers set up cross-account access for a monitoring or backup vendor, intend to restrict the principal later, and never add the ExternalId condition because the initial handshake with the vendor’s account succeeds without it. AWS Organizations SCPs do not block this by default, and IAM Access Analyzer will report the role as “external access allowed” only if it is actively scanning that specific resource type.

The Blast Radius

Because the trust policy authorises the root principal of every AWS account on the internet, not just the intended vendor, any external account that knows or guesses the role ARN can call sts:AssumeRole and receive temporary credentials scoped to whatever permissions policy is attached. This becomes a confused deputy problem: attackers who compromise or register throwaway AWS accounts can enumerate role ARNs from leaked CloudFormation templates, public GitHub repositories, or Terraform state files, then assume the role directly. CloudTrail logs the call as a legitimate, successfully authenticated AssumeRole event from a foreign account, which does not trigger GuardDuty’s anomalous-behaviour findings the way credential theft does. Once inside, the caller inherits whatever S3, KMS, or Secrets Manager access the role’s permissions policy grants, and session duration up to the role’s configured maximum extends the exposure window well past initial discovery.

The Lead Mechanic Fix

Replace the wildcard root principal with the specific trusted account ARN and enforce a unique sts:ExternalId per external party: "Condition": {"StringEquals": {"sts:ExternalId": ""}}. Run aws accessanalyzer list-findings --analyzer-arn against every role with an external principal and remediate any finding where the principal ARN contains a wildcard segment. For vendor integrations, generate the ExternalId server-side per customer, store it outside source control, and rotate it on any suspected leak rather than treating it as a permanent onboarding constant.

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

sts:ExternalId
"Condition": {"StringEquals": {"sts:ExternalId": ""}}
aws accessanalyzer list-findings --analyzer-arn
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

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