Join our Newsletter — 33% off our NHI Course
Home› Guides› AWS Role Chaining Detection: Following Attackers Across AssumeRole…
Guide Cloud & Workload Identity

AWS Role Chaining Detection: Following Attackers Across AssumeRole Hops in CloudTrail

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 12 November 2026 16 min read
On this page

Every AssumeRole hop in AWS replaces the caller's identity with a role session, so an attacker who chains roles across accounts can leave a CloudTrail trail in which each record looks like legitimate automation. This guide is about detection only: how to rebuild a chain of role sessions from CloudTrail, which fields carry identity through each hop, how source identity and transitive session tags make chains attributable, and the alert logic that separates normal pipeline chains from abuse. It assumes you already know how STS, trust policies and session tags work, which the AWS STS and AssumeRole Guide covers. It is written for detection engineers, cloud security teams and incident responders working in multi-account AWS Organizations. Field names and behaviour come from AWS IAM and CloudTrail documentation, checked on 12 November 2026.

This is an independent guide from NHI Mgmt Group, based on AWS's public documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.

Key takeaways

  • A chain is a graph, not a log line. You rebuild it by joining each AssumeRole event's responseElements.credentials.accessKeyId to the userIdentity.accessKeyId of the next hop.
  • Cross-account hops are logged twice. The caller's account holds the full caller identity and the target account holds only the caller's account and principal ID, matched by sharedEventID, so you need both sides centrally.
  • Source identity is the only identity that survives every hop. It cannot be changed once set, and it appears in userIdentity.sessionContext.sourceIdentity on every later call, so a privileged chain without it is an alert in itself.
  • Baselines beat signatures. Most chains are pipelines that take the same path every day; alert on new edges, new depths, new networks and chains that end in a privileged role.
  • Denied cross-account attempts are invisible in the target account. Probing of your roles shows up only in the caller's account, which may be the attacker's own.

What role chaining abuse looks like in the logs

AWS defines role chaining as using one role's temporary credentials to assume a second role, and caps any chained session at one hour regardless of the role's maximum session duration; a chained AssumeRole call with DurationSeconds above 3,600 fails. Attackers chain roles for the same reasons pipelines do: to cross account boundaries, to reach a role with more permissions, and to move from a compromised workload into the accounts it deploys to. The mechanics, trust policy conditions and the one hour cap are explained in the AWS STS and AssumeRole Guide; this page picks up where that guide's logging section stops.

The detection problem is that each hop launders identity. After the first hop, calls are recorded with userIdentity.type AssumedRole, and the only identity shown is the role session: arn:aws:sts::<account>:assumed-role/<role>/<session-name>, with the role in sessionContext.sessionIssuer. Nothing in that record says which person, pipeline job or stolen key started the chain unless something carried that context forward.

In ATT&CK v20 terms, chain abuse usually combines T1078.004 Valid Accounts: Cloud Accounts (using the stolen session or key), T1550.001 Use Alternate Authentication Material: Application Access Token (reusing temporary credentials), T1548.005 Temporary Elevated Cloud Access (assuming a more privileged role) and often T1098.003 Additional Cloud Roles when the attacker edits a trust policy so a role they control can assume a privileged one. Discovery calls such as T1087.004 Cloud Account and T1580 Cloud Infrastructure Discovery tend to follow each new hop.

STS calls are management events with eventSource sts.amazonaws.com. AssumeRole is a read-only event, but CloudTrail still records its responseElements (without the secret access key), which is what makes chain reconstruction possible.

FieldEventWhat it gives you
userIdentity.accessKeyIdEvery call, including the AssumeRole itselfThe key that signed the call: AKIA for long-term IAM user keys, ASIA for temporary credentials. The parent of this hop.
responseElements.credentials.accessKeyIdAssumeRole (caller side)The new ASIA key issued for the target role. The child of this hop.
responseElements.assumedRoleUser.arnAssumeRoleThe session ARN that later calls will carry in userIdentity.arn
requestParameters.roleArn and roleSessionNameAssumeRoleTarget role and the session name the caller chose
requestParameters.sourceIdentityAssumeRole where it is first set, or re-passedThe original actor; echoed in responseElements.sourceIdentity
userIdentity.sessionContext.sourceIdentityEvery later call in the session and in chained sessionsThe original actor carried through the chain
requestParameters.tags, transitiveTagKeys, incomingTransitiveTagsAssumeRoleSession tags set on this hop, which keys are transitive, and transitive tags inherited from the calling session
requestParameters.principalTagsAssumeRoleWithSAML and AssumeRoleWithWebIdentityTags supplied by the identity provider at the start of a federated chain
userIdentity.sessionContext.sessionIssuerEvery call made with a role sessionThe role (type Role, arn, accountId, userName) behind the session
userIdentity.sessionContext.attributesEvery role session callcreationDate and mfaAuthenticated
sharedEventIDCross-account AssumeRoleJoins the caller-account record to the target-account record
additionalEventData.RequestDetails.endpointTypeSTS callsglobal or regional; global endpoint calls are logged in US East (N. Virginia), regional calls in the serving Region

Two caveats from the CloudTrail userIdentity reference matter for joins. First, userIdentity.accessKeyId may be absent or an empty string, so a join on keys alone will have gaps and needs the session ARN plus time window as a fallback. Second, for AssumedRole the userName field is not set at the top level; read sessionContext.sessionIssuer.userName for the role name.

Rebuilding a chain step by step

Chain reconstruction is the core investigative skill here, and the same logic drives the automated detections in the next sections. The steps assume an organisation trail or CloudTrail Lake event data store that collects management events from every account and every Region. See the AWS CloudTrail Guide for collection design.

  1. Start from the suspicious call. Take its userIdentity.accessKeyId (an ASIA key), userIdentity.arn and eventTime.
  2. Find the issuing AssumeRole. Search sts.amazonaws.com AssumeRole events where responseElements.credentials.accessKeyId equals that key. If the key is missing, match responseElements.assumedRoleUser.arn to the session ARN in a window of up to 12 hours before the call (one hour if the session was itself chained).
  3. Read the parent. The issuing event's userIdentity.accessKeyId is the parent credential. If it begins AKIA, you have reached a long-term IAM user key: the chain root. If it is ASIA, repeat step 2 for that key.
  4. Cross the account boundary. Where the issuing event sits in the target account with userIdentity.type AWSAccount, find the caller-side record in the calling account with the same sharedEventID. Only the caller-side record shows the full caller ARN and key.
  5. Handle federated and service roots. A chain that begins with AssumeRoleWithWebIdentity or AssumeRoleWithSAML has its root in the identity provider: record the federated subject, webIdFederationData and principalTags. A chain that begins with an EC2 instance profile, ECS task role or Lambda execution role has a workload root; record the instance, task or function.
  6. Record the path. For each hop keep account, role ARN, session name, source identity, transitive tags, source IP, user agent and creation time. The ordered list of role ARNs is the chain's signature, which you compare with the baseline.
  7. Fan out. From each ASIA key in the chain, list every other API call it made. Attackers often branch from an intermediate hop, so the damage is not only at the end of the chain.

For the starting point of an investigation from a leaked long-term key, see How to Investigate CloudTrail for a Compromised Access Key.

Making chains attributable with source identity and transitive tags

Reconstruction by key joins works, but it is slow and breaks when a hop's log is missing. Source identity and transitive session tags put the answer on every record, which is what turns chain analysis into a single field lookup.

  • Source identity: set with the SourceIdentity parameter on AssumeRole, the SAML attribute https://aws.amazon.com/SAML/Attributes/SourceIdentity, or the JWT claim https://aws.amazon.com/source_identity. It is 2 to 256 characters, cannot begin with aws:, cannot be changed once set, and persists through role chaining; a chained AssumeRole that passes a different value is denied. It is visible in userIdentity.sessionContext.sourceIdentity on every later call. Setting it needs sts:SetSourceIdentity in both the caller's permissions and the target trust policy, including on every hop of a chain.
  • Condition keys for enforcement: sts:SourceIdentity is present when the value is first set; aws:SourceIdentity is present on later requests in the session and in chained role requests. Requiring aws:SourceIdentity in the trust policy of a privileged role means no chain can reach it without a named actor.
  • Transitive session tags: by default session tags are not passed to the next session. Tags whose keys are listed in TransitiveTagKeys persist through every later hop and appear in requestParameters.incomingTransitiveTags. Only session tags can be transitive, not role tags, and the trust policy's sts:TransitiveTagKeys condition caps which keys a caller may mark. A tag such as pipeline-run or change-ticket that is transitive gives every hop a correlation ID.
  • Limits to plan for: AWS does not control the value of source identity; your identity provider or pipeline must set it from a trusted attribute. The IAM documentation also states that source identity is not captured when an AWS service or service-linked role acts on behalf of a federated or workforce identity, so those paths still need key-based reconstruction.
Chain observationWithout source identity or tagsWith both enforced
Who started a three-hop chain into productionJoin three AssumeRole events across accounts by access key and sharedEventIDRead sessionContext.sourceIdentity on any production call
Which pipeline run made a changeInfer from session names, if the pipeline sets them consistentlyRead the transitive run tag in incomingTransitiveTags
Was a privileged role reached by an unexpected actorCompare chain paths with a baselineTrust policy denies the hop; the caller side logs a failure
Did an attacker insert a hopNew edge in the chain graphNew edge plus a source identity that does not match the edge's usual actors

Alert logic for unusual chains

Good chain detections compare each new hop with what that role normally does. Build the baseline from 30 to 90 days of AssumeRole events: for each target role, the set of calling roles (edges), the source identities and session-name patterns seen, the source IP ranges or VPC endpoints, and the usual depth at which the role is reached.

DetectionLogicTypical benign cause to tune outPriority
New edge into a privileged roleAssumeRole where the pair (caller sessionIssuer.arn, requestParameters.roleArn) is not in the baseline and the target is tagged privilegedNew pipeline or account onboarding with a change ticketHigh
Privileged hop without source identityAssumeRole into a privileged role where requestParameters.sourceIdentity and incoming aws:SourceIdentity are both emptyRoles not yet migrated; track as debtHigh
Source identity mismatchsessionContext.sourceIdentity on a session that is not among the actors usually seen for that role, or that names a disabled userStaff changing teamsHigh
Unusual depthChain length above the role's baseline (for example, a role normally reached in one hop reached in three)Break-glass proceduresMedium
Loop or revisitThe same role ARN appears twice in one chain, or a chain returns to its origin accountRare; review each caseMedium
Session used from a new networkCalls with an ASIA key from an IP or ASN not seen for the issuing role, especially one that differs from the IP that called AssumeRoleCorporate VPN egress changesHigh
Rapid fan-outOne session calls AssumeRole into many roles or accounts within minutesOrganisation-wide audit tooling, if it has its own baselineMedium
Trust edit then hopUpdateAssumeRolePolicy on a role followed by an AssumeRole into that role from a new callerInfrastructure-as-code deploy that changed trust deliberatelyHigh
Discovery after a hopGetCallerIdentity, ListRoles or ListAccounts shortly after a new edgeInventory toolsLow alone, raise with others
Failed hop burst in the caller accountRepeated AccessDenied on AssumeRole from one session across many role ARNsMisconfigured deploymentMedium

RoleSessionName is chosen by the caller (2 to 64 characters), so an attacker can copy a pipeline's naming pattern. Treat it as a weak signal that helps triage, never as attribution. If you want session names enforced, the trust policy can condition on sts:RoleSessionName, which turns a naming mismatch into a denied call on the caller side.

Where managed services help

Amazon GuardDuty's IAM finding types include UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS and .InsideAWS for EC2 instance credentials used elsewhere, ResourceCredentialExfiltration.OutsideAWS and .InsideAWS for ECS task and Lambda credentials, and a family of AnomalousBehavior findings such as PrivilegeEscalation:IAMUser/AnomalousBehavior and Discovery:IAMUser/AnomalousBehavior. The exfiltration findings are the most useful for chains that start from a workload role. GuardDuty does not reconstruct chain paths for you, so keep the custom graph logic above. See the Amazon GuardDuty Guide.

Rolling out chain detection

  1. Centralise both sides. Use an organisation trail covering all accounts and Regions, delivered to a log archive account the workloads cannot write to. Without the caller-side records, cross-account hops lose their caller identity.
  2. Tag privileged roles. Mark administrative, deployment, security tooling and break-glass roles with a consistent tag so detections can scope to them.
  3. Build the edge baseline. Extract every AssumeRole for 30 to 90 days into a table of edges with counts, actors, networks and depth. Review it with platform owners: unexpected edges found at this stage are often live risk, not noise.
  4. Deploy alerts in audit mode. Run the table's detections as reports for two to four weeks, measure volume per rule and tune exclusions to named pipelines and tickets, not to whole accounts.
  5. Introduce source identity. Configure the identity provider and pipelines to set it, add sts:SetSourceIdentity to every hop's trust policy, alert on privileged hops without it, then require aws:SourceIdentity on privileged roles. Pilot in one account first; a missing permission on any hop makes the chained call fail, and rollback is restoring the previous trust policy from version control.
  6. Add transitive correlation tags. Have pipelines pass a run or ticket tag marked transitive, constrained by sts:TransitiveTagKeys in trust policies.
  7. Promote to paging. Move high-priority rules to on-call once false positives are below an agreed rate, and link each alert to a chain reconstruction query so the responder starts with the full path.

Small versus large estates: a handful of accounts can baseline edges by hand and alert on any new edge into a privileged role. Organisations with hundreds of accounts should generate the edge baseline automatically, enforce source identity through trust policy templates in code, and use the AWS Organizations and SCPs Guide patterns to stop trust policies being edited outside the pipeline.

Measuring whether it works

The targets below are NHI Mgmt Group recommendations, not AWS figures.

  • Privileged hops with source identity: share of AssumeRole events into privileged roles that carry a source identity; target 100 percent.
  • Chain reconstruction time: median minutes for a responder to go from a suspicious call to the chain root; target under 15 minutes.
  • Unbaselined edges: count of new caller-to-role edges per week, and the share explained by a change ticket.
  • Log completeness: share of cross-account AssumeRole events whose sharedEventID has both caller-side and target-side records in the central store.
  • Alert precision: share of high-priority chain alerts confirmed as true positives or policy breaches after triage.

Common failure patterns

  • Collecting only the target account's logs: cross-account hops then show userIdentity.type AWSAccount with no caller ARN or key, and the chain stops at the account boundary.
  • Collecting only us-east-1 or only your home Region: regional STS endpoint calls are logged in the Region that served them, so hops made through other Regions are missing.
  • Treating session names as identity: callers choose them, and attackers reuse familiar names to blend in.
  • Ignoring session reuse from new networks: in the Bybit hack, attackers reused a developer's active AWS session tokens from VPN addresses; an alert on a known session key appearing from a new network is the control that fits that pattern.
  • Allowing trust policy edits outside change control: an attacker who can call UpdateAssumeRolePolicy can add their own edge to a privileged role, and the chain then looks authorised.
  • Waiting for denied attempts in the target account: CloudTrail does not log denied cross-account STS requests in the target account, so failed probing is visible only from the calling side.

Framework mapping

FrameworkReferenceHow chain detection supports it
NIST CSF 2.0DE.CM-03, DE.AE-02, PR.AA-05Monitoring of role session activity, analysis of chains, least privilege on trust edges
NIST SP 800-53 Rev. 5AU-2, AU-6, AU-12, SI-4, IA-4, AC-6STS event logging and review, monitoring, identifier management through source identity, least privilege
CIS Controls v8.18 Audit Log Management, 6 Access Control ManagementCentralised CloudTrail, review of role access paths
ISO/IEC 27001:2022 Annex A8.15 Logging, 8.16 Monitoring activities, 8.2 Privileged access rightsCollection and monitoring of role sessions, control of privileged roles
MITRE ATT&CK v20T1078.004, T1550.001, T1548.005, T1098.003, T1087.004, T1580Stolen sessions, temporary elevation, trust policy changes and post-hop discovery

Practitioner checklist

  • Collect CloudTrail management events from every account and Region into one log archive.
  • Confirm both caller-side and target-side AssumeRole records arrive for cross-account hops.
  • Tag privileged roles consistently so detections can scope to them.
  • Build and review a 30 to 90 day baseline of caller-to-role edges, actors and networks.
  • Save a chain reconstruction query that joins issued and signing access keys.
  • Alert on new edges into privileged roles and on privileged hops without source identity.
  • Set source identity from the identity provider and pipelines, then require aws:SourceIdentity on privileged roles.
  • Pass a transitive correlation tag from pipelines and constrain it with sts:TransitiveTagKeys.
  • Alert on UpdateAssumeRolePolicy followed by a new edge into the same role.
  • Measure source identity coverage and reconstruction time monthly.

Standards and references

Related NHI Mgmt Group resources: AWS STS and AssumeRole Guide · AWS CloudTrail Guide · How to Investigate CloudTrail for a Compromised Access Key · AWS IAM Policies and Roles Guide · Amazon GuardDuty Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 12 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.