AWS IAM Trust Policy Analyzer

A trust policy answers one question: who may become this role. The commonest misreading turns a narrow-looking policy into a delegation to an entire AWS account.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Analyze. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

An account root principal

Delegates to the entire account, which is not what it looks like

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

GitHub OIDC without a subject check

Assumable from every repository on GitHub, not just yours

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com" },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } }
    }
  ]
}

A service principal with no source guard

The confused deputy problem, for a principal every AWS customer shares

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "s3.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Trusting an account root to keep the grant narrow

    It delegates to the whole account, so any principal there whose IAM policy allows the call can assume the role.

    Instead:Name the specific role or user ARN. It is still subject to that principal's own policy.

  2. Adding an OIDC provider with only an aud condition

    aud is the same value for every identity that provider serves, so the role is assumable by all of them, which for GitHub Actions means every repository on GitHub.

    Instead:Add a condition on the sub claim, and check the exact format for your provider.

  3. Trusting an AWS service principal with no source condition

    The principal is shared by every customer of that service, so it can be pointed at your role from another account's resource.

    Instead:Add aws:SourceAccount with your account id, and aws:SourceArn where you can be that specific.

An account root principal is not the root user

arn:aws:iam::123456789012:root in a trust policy means that account may decide for itself who assumes the role. Trust is delegated to its administrators, not restricted to its root user.

Which makes it right for an account you control and wide for one you do not

Any principal in that account whose own IAM policy allows sts:AssumeRole on this ARN can then do so, without anybody in your account being involved. Naming the specific role ARN instead is one more character of typing and a much narrower grant.

An OIDC provider without a subject condition trusts everybody it can issue for

For GitHub Actions that is every repository on GitHub, not just yours. Checking only the aud claim is not enough, because aud is the same value for every repository. The sub condition is the whole control.

Service principals are shared by every AWS customer

So a trust policy naming s3.amazonaws.com with no aws:SourceAccount or aws:SourceArn condition will let the service assume your role on behalf of a bucket in somebody else's account. That is the confused deputy problem, and AWS documents the guard for exactly this reason.

Both sides have to allow it

The trust policy must permit the principal AND the principal's own IAM policy must allow sts:AssumeRole on the role ARN. An access denied says which, so a cross-account failure means checking a policy you may not be able to see.

The action has to match how the caller arrives

OIDC uses sts:AssumeRoleWithWebIdentity and SAML uses sts:AssumeRoleWithSAML. A federated principal paired with plain sts:AssumeRole is refused with an error naming neither the action nor the mismatch.

A trust policy has no Resource element

The resource is the role itself. Including one produces a MalformedPolicyDocument error that names the document rather than the element.