# The Hidden Path: Lateral Movement Through IAM Trust Policy Modification

> How attackers leverage UpdateAssumeRolePolicy to move laterally across AWS environments, and why traditional permission analysis often misses this vector.

* URL: <https://blog.paniam.cloud/posts/lateral-movement-trust-policy>
* Author: Jean-Yves Pasquier
* Published: 2026-01-20
* Tags: lateral movement, aws security, iam

When security teams audit cloud permissions, they typically focus on what actions
each identity can perform. Can this role read from that S3? Can that user modify
these serverless functions? This approach makes sense—it maps directly to how
we think about access control. But it misses a crucial category of
permissions: those that don't grant access directly, but enable an attacker to
_create_ access where none existed before.

The [`iam:UpdateAssumeRolePolicy`](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAssumeRolePolicy.html)
permission (with equivalents in
[Azure](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal)
and [GCP](https://cloud.google.com/iam/docs/granting-changing-revoking-access))
is one such capability. It doesn't let a user assume a role or access any
resource directly.
Instead, it lets them modify _who_ can assume a role. That
distinction makes it one of the most dangerous and overlooked
lateral movement vectors in complex cloud environments.
Let's take a closer look at how it works with an example on AWS.

## Understanding IAM Role Trust Policies

AWS role assumption works through a
[dual-policy mechanism](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html).
When a principal attempts to assume a role, AWS evaluates two separate policies:

1. **Identity-based policy**: Does the calling principal have permission to call
   `sts:AssumeRole` on the target role ? Not that it can be optional for role
   assumtion when the assumer is the same as the role owner.
2. **Trust policy**: Does the target role's trust policy list the calling
   principal as a trusted entity?

Both conditions must be satisfied for the assumption to succeed. The
[trust policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)
lives on the role itself as its "assume role policy document" and defines
which principals (users, roles, services, or even external AWS accounts) are
allowed to assume that role.

This dual mechanism provides defense in depth—you need both the caller to have
permission to assume _and_ the role to trust the caller. However, it also
creates a non-obvious attack surface: **what happens when someone can modify
the trust policy itself?**

![Detecting trust policy modification permissions as a first step in eliminating the vulnerability](https://blog.paniam.cloud/_astro/path_modify_trust_policy.DoRhM6FR.png)

## The UpdateAssumeRolePolicy Attack Vector

An attacker with the `iam:UpdateAssumeRolePolicy` permission can perform lateral
movement in two steps:

### Step 1: Modify the trust policy

The attacker adds their own principal (or one they control) to the target role's
trust policy. This is a single API call that immediately takes effect.

### Step 2: Assume the role

With the trust policy now permitting them, the attacker assumes the role and
inherits all of its permissions.

Here's what this looks like in practice using the
[AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/iam/update-assume-role-policy.html):

```bash
# Step 1: Modify the trust policy to add attacker's principal
aws iam update-assume-role-policy \
  --role-name TargetRole \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/attacker"
      },
      "Action": "sts:AssumeRole"
    }]
  }'

# Step 2: Assume the role
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/TargetRole \
  --role-session-name AttackerSession
```

This attack is particularly dangerous for several reasons:

- **Speed**: A single API call modifies the trust relationship, and assumption
  is immediate
- **Bypasses existing restrictions**: It doesn't matter who the role _currently_
  trusts—the attacker rewrites the trust policy entirely
- **Persistence**: The modified trust policy remains in effect until someone notices
  and reverts it. A smart attacker would simply add a new principal to the trust
  policy, which would not break any existing workflow. This allows them to go
  unnoticed for a long time.
- **Audit blind spots**: Permission audits that only examine _current_ trust
  relationships won't flag the risk

## Why Traditional Analysis Misses This

Most security tools answer the question: "Who can assume this role?" They do
this by reading the role's current trust policy and mapping the trusted
principals. This approach has a fundamental limitation: it only shows the
_current state_ of trust relationships, not _who could modify them_.

The permission to call `iam:UpdateAssumeRolePolicy` exists on identity-based
policies attached to users and roles, not on the trust policy itself. Auditing
a role's trust policy only reveals who is trusted _right now_. The real risk
often lies with principals who _aren't_ currently trusted but could add
themselves to the list.

This creates a blind spot: a principal with zero current access to a role can
grant themselves full access with a single API call. Traditional tools that only
enumerate existing trust relationships will never surface this path.

## Mapping the Full Attack Path

To understand the true risk landscape, security analysis must consider both
dimensions:

| Analysis Type               | Question Answered                        | Tools Typically Check |
| --------------------------- | ---------------------------------------- | --------------------- |
| Trust relationship analysis | Who can assume this role today?          | Yes                   |
| IAM action analysis         | Who can modify this role's trust policy? | Often missed          |

The combination reveals attack paths invisible to simple reachability analysis.
A developer role might have `iam:UpdateAssumeRolePolicy` permission
on production roles for legitimate infrastructure automation. That developer
role becomes a pivot point: compromising it grants access not just to what it
can do directly, but to everything the production roles can access.

Graph-based visualization makes these indirect paths visible. Security teams
can trace the full attack chain: a compromised identity that can modify the
trust policy of a target role, which in turn has access to sensitive resources.

## Why Restricting AssumeRole Isn't Enough

A natural defensive response is to restrict which principals can call
`sts:AssumeRole` on sensitive roles. You might create identity-based policies
that deny certain users or roles from assuming critical roles. However, this
defense has a significant gap when combined with trust policy modification—a
variant of the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).

Consider this scenario:

1. An attacker compromises a principal with `iam:UpdateAssumeRolePolicy`
   permission on a sensitive role
2. The attacker cannot assume the role directly—there's an explicit deny in
   their identity-based policy
3. The attacker modifies the trust policy to trust an **external AWS account
   they control**
4. From that external account, the attacker creates any principal they want
5. That external principal assumes the role, bypassing all identity-based
   restrictions in the victim account

The key insight: **the attacker doesn't need to compromise an existing trusted
principal—they can create one**. Identity-based denies in the victim account
have no effect on principals in other accounts. The only thing that matters
for [cross-account assumption](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html)
is the trust policy, which the attacker now controls.

This is why `iam:UpdateAssumeRolePolicy` is not just a privilege escalation
risk within an account—it's a potential entry point for external attackers to
establish persistent access.

## Defense in Depth: SCPs and RCPs

Defending against trust policy modification attacks requires layered controls
that operate at different levels of the
[AWS authorization model](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html).

### Service Control Policies (SCPs)

[SCPs](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)
apply at the AWS Organizations level and can restrict which principals can
call `iam:UpdateAssumeRolePolicy` across your entire organization:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RestrictTrustPolicyModification",
      "Effect": "Deny",
      "Action": "iam:UpdateAssumeRolePolicy",
      "Resource": "*",
      "Condition": {
        "StringNotLike": {
          "aws:PrincipalArn": [
            "arn:aws:iam::*:role/InfrastructureAutomationRole"
          ]
        }
      }
    }
  ]
}
```

This approach limits trust policy modification to specific, tightly controlled
roles, reducing the attack surface significantly. See the
[SCP examples documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_examples.html)
for more patterns.

### Resource Control Policies (RCPs)

[RCPs](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html)
provide a second line of defense by restricting _who can assume roles_ in
your account, regardless of what the trust policies say:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyExternalAssumption",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "sts:AssumeRole",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalOrgID": "o-your-org-id"
        }
      }
    }
  ]
}
```

Even if an attacker modifies a trust policy to trust an external account, the
RCP blocks the actual assumption. This prevents the external account pivot
described earlier. See the
[RCP examples documentation](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps_examples.html)
for additional patterns.

### Additional Mitigations

- **CloudTrail monitoring** allows security teams to create alerts on
  `UpdateAssumeRolePolicy` calls, especially those that add external principals
  or wildcard trusts.
- **Permission boundaries** limit the scope of what roles can do even if their
  trust policies are modified.
- **Regular audits** should include trust policy modification permissions in
  privilege escalation assessments, not just current trust relationships.

The layered approach is essential: SCPs prevent the modification where possible,
RCPs block exploitation if modification occurs, and monitoring provides
visibility into attempted attacks.

## Detecting Prior Compromises

What if the attack already happened before you deployed security tooling? Trust
policy modifications don't trigger alerts retroactively, and CloudTrail logs
are often retained for only 90 days. An attacker who modified a trust policy
months ago may have established persistent access that traditional audits
won't catch.

This is where graph-based analysis becomes invaluable for detection, not just
prevention. When PanIAM maps your environment's trust relationships, any role
trusting an external account outside your organization appears as an inbound
edge from an unknown principal, highlighted in red. These edges immediately
stand out: why would a production role in your account trust an AWS account
you don't recognize?

In a healthy environment, cross-account trust should only exist with:

- Other accounts in your AWS Organization
- Known partner or vendor accounts with documented business relationships
- AWS service principals for legitimate integrations

Any trust relationship outside these categories warrants immediate
investigation. It could be a legitimate configuration you forgot about, or it
could be evidence of a prior compromise where an attacker added their external
account to maintain persistent access.

The graph makes this anomaly visible at a glance. Instead of manually reviewing
hundreds of trust policies line by line, you can spot the suspicious red edge
pointing to an unknown account and trace exactly which roles are affected and
what those roles can access.

## Thinking Like an Attacker

Attackers don't analyze permissions in isolation—they think in graphs and paths.
A permission that seems innocuous on its own might be the critical link in a
chain leading to sensitive data. The `iam:UpdateAssumeRolePolicy` permission
is a prime example: it grants no direct access to anything, but it can unlock
access to everything a target role can reach.

Security teams need the same graph-based perspective. Understanding your
environment's attack paths requires modeling not just what each identity can
access today, but what access they could _create_ through indirect actions.
Without this view, defenders are perpetually one step behind attackers who
naturally think in these terms.

At PanIAM, we model these indirect paths to surface lateral movement
opportunities that traditional permission analysis misses. The permissions
that matter most aren't always the ones that grant access—sometimes they're
the ones that let attackers grant it to themselves.
