AWS Cross-Account AssumeRole Is Denied by a Mismatched Trust Policy
Trace an AWS STS cross-account AssumeRole denial across both accounts and repair a mismatched role trust policy with a controlled rollback.
Destructive Operation
This intervention contains destructive operations. Proceed with extreme caution and ensure database backups exist before execution.
01 // Diagnose
Symptom
A workload or operator in one AWS account receives AccessDenied when calling STS AssumeRole for a role in another account, although the role name and account IDs appear correct.
Detection Signature
-
From the calling identity, run
aws sts get-caller-identityand record the exact account and principal ARN. -
Reproduce once with
aws sts assume-role --role-arn arn:aws:iam::<TARGET_ACCOUNT_ID>:role/<TARGET_ROLE> --role-session-name incident-diagnosticand retain the request ID and error. -
In the target account, run
aws iam get-role --role-name <TARGET_ROLE> --query 'Role.AssumeRolePolicyDocument'and decode/review the trust policy Principal, Action, and Condition elements. -
Review CloudTrail events for
AssumeRoleat the incident timestamp. -
Check applicable identity policies, permissions boundaries, session policies, service control policies, and resource control policies for an explicit or implicit deny.
Root Cause Analysis
-
Cross-account AssumeRole requires permission on both sides: the calling principal needs an identity-based allow for sts:AssumeRole, and the target role trust policy must trust the correct principal under its conditions.
-
A stale principal ARN, incorrect account ID, unmet ExternalId condition, or applicable explicit deny causes the request to fail.
02 // Contain & Prevent
Blast Radius
Automations that depend on the target role cannot obtain temporary credentials.
Deployments, backups, or incident tooling may stop if they use the affected cross-account path.
An overly broad emergency trust-policy change could expose the target role to unintended principals.
Prevention Measures
-
Manage role trust policies through reviewed infrastructure as code and test them with a dedicated non-production principal.
-
Use stable role ARNs and explicit conditions rather than broad principals.
-
Alert on repeated AssumeRole AccessDenied events and unexpected trust-policy changes through CloudTrail.
-
Include both trusted-account and trusting-account policy evaluation in access reviews.
03 // Fix & Intervention
Pre-Flight Checks
-
Confirm the current AWS CLI profile, region-independent account context, and exact caller ARN with
aws sts get-caller-identity; do not infer identity from a role name. -
Export the current target role with
aws iam get-role --role-name <TARGET_ROLE> > target-role-before-response.json, then extract its AssumeRolePolicyDocument intotarget-trust-policy-before.jsonand validate that rollback file before changing anything. -
IAM provides no native dry-run for
update-assume-role-policy. -
Use
jq empty validated-trust-policy.jsonandaws accessanalyzer validate-policy --policy-type RESOURCE_POLICY --validate-policy-resource-type AWS::IAM::AssumeRolePolicyDocument --policy-document file://validated-trust-policy.jsonas the equivalent policy preview; abort on any error-severity finding. -
Peer-review the validated policy and a diff against
target-trust-policy-before.json; -
confirm it changes only the intended Principal or Condition.
-
Confirm the caller's identity policy permits
sts:AssumeRoleon the exact target role ARN, then useaws iam simulate-principal-policywhere supported to preview the caller-side identity-policy decision. -
Check Organizations policies, permissions boundaries, and session policies for denies that remain independently authoritative even if the target trust policy is repaired.
-
Confirm the operator is authorized to update the exact target role in the target account.
-
Obtain the target-account owner's approval and define a five-minute abort window.
Execution CommandsCOMMANDS
jq -r '.Role.AssumeRolePolicyDocument' target-role-before-response.json | python3 -c 'import json,sys,urllib.parse; value=urllib.parse.unquote(sys.stdin.read().strip()); print(json.dumps(json.loads(value),indent=2))' > target-trust-policy-before.json
jq empty target-trust-policy-before.json validated-trust-policy.json
aws accessanalyzer validate-policy --policy-type RESOURCE_POLICY --validate-policy-resource-type AWS::IAM::AssumeRolePolicyDocument --policy-document file://validated-trust-policy.json
aws iam update-assume-role-policy --role-name <TARGET_ROLE> --policy-document file://validated-trust-policy.json
aws iam get-role --role-name <TARGET_ROLE> --query 'Role.AssumeRolePolicyDocument'
04 // Verify & Recover
Verification Steps
-
Retry
aws sts assume-rolefrom the intended caller and confirm temporary credentials are returned. -
Use the temporary credentials for one read-only target operation that the role is expected to allow.
-
Confirm CloudTrail records the successful AssumeRole event with the intended principal and conditions.
-
Verify an unrelated test principal still receives AccessDenied.
-
Monitor AssumeRole activity for at least 15 minutes for unexpected principals.
Rollback Protocol
- If the new trust policy admits an unintended principal or does not resolve the incident, restore the already extracted and validated
target-trust-policy-before.jsonwithaws iam update-assume-role-policy --role-name <TARGET_ROLE> --policy-document file://target-trust-policy-before.json, retrieve and compare the restored policy, and revoke any temporary sessions created during testing where supported by the incident response plan.
Escalation
-
An Organizations SCP/RCP or permissions boundary is responsible for the denial.
-
The original trusted principal was deleted and recreated, changing its principal identity.
-
The repair would require trusting an entire external account without approved restrictive conditions.
-
CloudTrail shows unexpected successful sessions or evidence of credential misuse.
Authoritative Sources
Cross-account policy evaluation logic
Both the trusted and trusting accounts must permit a cross-account request.
Troubleshoot access denied error messages
Diagnosis of implicit and explicit denies across applicable AWS policy types.
Policy evaluation logic
AWS authorization evaluation and the precedence of explicit deny.
AWS CLI update-assume-role-policy
The supported AWS CLI operation and parameters for updating a role trust policy.