A Trust Policy (also called a role trust relationship) is a JSON policy attached to an IAM role that specifies who can call sts:AssumeRole on it. Without a trust policy allowing a principal, that principal cannot assume the role, even if their own IAM policy grants sts:AssumeRole.
Trust policies use the same syntax as IAM policies but with a Principal element instead of being attached to a principal.
"Service": "ec2.amazonaws.com" (for EC2 instance roles)"AWS": "arn:aws:iam::123456789012:root""AWS": "arn:aws:iam::123456789012:role/MyRole"Trust policies fail in two well-documented ways. The first is the over-broad account principal. Trusting arn:aws:iam::123456789012:root does not mean "the root user of account 123456789012": it means "any principal in that account which its own administrators allow to assume roles". That is a deliberate delegation of authorization to the other account's IAM hygiene. Fine when the account is yours and well-governed; dangerous when it belongs to a vendor whose internal access controls you cannot see. When the requirement is really "this one pipeline role in the partner account", name that role ARN as the principal instead of the account root.
The second is the confused deputy problem. A third-party service assumes a role in your account to do its job, and the same service does this for hundreds of customers using role ARNs, which are not secrets. Without an extra check, another customer of that vendor could hand the vendor your role ARN and have the vendor act on your account. AWS documents the fix precisely: the vendor generates a unique external ID per customer (usually a GUID, controlled by the vendor, not chosen by you), and your trust policy requires it with a condition:
"Condition": { "StringEquals": { "sts:ExternalId": "12345" } }
For the cross-service variant, where an AWS service principal like cloudtrail.amazonaws.com writes to your resources, AWS recommends conditioning resource policies on aws:SourceArn, aws:SourceAccount, aws:SourceOrgID, or aws:SourceOrgPaths so the service can only act on behalf of resources and accounts you expect.
The trust policy is stored on the role itself and comes back with a single call:
aws iam get-role --role-name MyRole --query "Role.AssumeRolePolicyDocument"
Review three things in the output: the Principal (is it a whole account where a specific role would do?), the Action (roles assumed via OIDC should use sts:AssumeRoleWithWebIdentity, with conditions pinning the repository or subject claim), and the Condition block (third-party cross-account trusts should carry sts:ExternalId). Auditing every role this way in a loop, and flagging any trust policy whose principal is an account root outside your organization, is one of the highest-value IAM reviews you can automate.
What is the difference between a trust policy and a permissions policy?
The trust policy answers "who may become this role"; the permissions policies answer "what the role can do once assumed". Both gates must pass. A common misconception is that granting a user sts:AssumeRole in their identity policy is enough: it is not, because the role's trust policy must also name (or match) that principal.
Does trusting an account's root ARN grant access to the root user only?
No. The account root ARN in a Principal element represents the account itself, delegating the decision of which specific users or roles can assume your role to that account's own IAM policies. If you need to trust exactly one identity in another account, put that identity's ARN in the Principal element.
Is the external ID a secret like a password?
Not exactly. It is a customer-scoped identifier generated and controlled by the third party, typically a GUID, whose job is to bind the vendor's AssumeRole calls to the correct customer. Its security value comes from the vendor always sending the external ID of the customer who initiated the request, so another customer cannot steer the vendor toward your role even if they know your role ARN. That is also why you must receive the external ID from the vendor rather than inventing one yourself: an external ID the customer chooses defeats the mechanism, because the whole point is that the vendor, not the customer, controls which ID accompanies each request.
An AWS identity with temporary credentials that can be assumed by users, services, or applications to perform actions without long-term access keys.
The process of obtaining temporary security credentials by calling AWS STS to take on the permissions of an IAM role.
The ability to grant permissions for identities in one AWS account to access resources in another, typically using IAM roles with trust policies.
A security vulnerability where a trusted service is tricked into acting on behalf of an unauthorized party, typically prevented in AWS using external ID conditions.
Toc Consulting: AWS Security & Cloud Architecture
Our team helps engineering teams secure and architect AWS the right way: assessment in week one, a prioritized action plan in week two.