Pre-Beta Pre-beta signups are open now. The full audytx engine is live for pre-beta. Everything free today stays free — paid tiers arrive Sep 01, 2026 from $20/month for unlimited repositories.
AWS IAM · privilege escalation · detection reference

All 31 documented AWS IAM privilege-escalation paths

A path-by-path reference. Each entry names the exact IAM actions the escalation needs — cited to AWS's own documentation — the mechanism in one line, and how audytx catches it by reasoning about the whole resource graph rather than matching a single statement. The catalog follows the BishopFox iam-vulnerable corpus and the Rhino Security Labs escalation-methods research that named most of them.

What "privilege escalation" means in IAM

Every path here has the same shape: a principal is granted a permission that does not look like admin, but can be used to obtain admin.

A policy that lets a principal run iam:CreatePolicyVersion isn't labeled "administrator" — but the principal can write a new default version of a policy it's already attached to and grant itself *. A policy with iam:PassRole plus lambda:CreateFunction lets the principal hand an admin role to a function it writes and invoke it. The danger is never in one action's name; it's in what the action reaches. That is exactly why single-resource pattern-matchers struggle here — they can flag iam:PassRole everywhere (and drown you in noise) or stay quiet (and miss the chain). Reasoning about the path is the only way to get both recall and precision.

How to read each entry. Requires lists the IAM actions the path depends on, each linked to its AWS API reference (the authoritative source for what the action does). Detected by audytx notes the class of reasoning that catches it. On the iam-vulnerable benchmark, audytx reaches full recall across all 31 — the measured numbers, methodology, and the per-tool comparison are on the IAM security page and the benchmark.
Group A · PassRole to a compute service (7 paths)

The classic chain: iam:PassRole lets a principal hand an existing privileged role to a service it can launch, and the service runs code as that role. Passing a role is not itself admin — it becomes escalation when paired with a service-launch action, which is why audytx scores the pair, not the PassRole alone.

01PassRole → Lambda

Create a function with a privileged execution role, then invoke it — the function's code runs with the role's permissions.

Requires · iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction
Detected by audytx · flagged as a privilege-escalation-capable grant; escalated to a Critical end-to-end attack path when the chain is reachable from an internet entry point.

02PassRole → EC2

Launch an EC2 instance with a privileged instance profile, then reach its credentials through the instance metadata service.

Requires · iam:PassRole + ec2:RunInstances
Detected by audytx · privilege-escalation-capable grant; the instance-profile chain also feeds the cross-resource attack-path search.

03PassRole → CloudFormation

Create or update a stack that CloudFormation deploys using a passed admin role, so the stack acts with those permissions.

Requires · iam:PassRole + cloudformation:CreateStack
Detected by audytx · privilege-escalation-capable grant (stack-role pass).

04PassRole → Glue

Create a Glue job whose execution role is admin, then start it — the job's script runs as the role.

Requires · iam:PassRole + glue:CreateJob + glue:StartJobRun
Detected by audytx · privilege-escalation-capable grant.

05PassRole → SSM (run command)

Run a command on an EC2 instance that already carries a privileged instance profile, executing as that role without launching anything new.

Requires · ssm:SendCommand (+ ssm:StartSession) on an instance with an admin profile
Detected by audytx · privilege-escalation-capable grant (run-command on a privileged instance).

06PassRole → Data Pipeline

Create a pipeline whose activation runs tasks under a passed admin role.

Requires · iam:PassRole + datapipeline:CreatePipeline + datapipeline:PutPipelineDefinition
Detected by audytx · privilege-escalation-capable grant.

07PassRole → SageMaker

Create a SageMaker training job (or notebook) with an admin execution role and read the role's credentials from inside it.

Requires · iam:PassRole + sagemaker:CreateTrainingJob
Detected by audytx · privilege-escalation-capable grant.
Group B · Service-role escalation (6 paths)

The same passing-a-role idea, through CI/CD and orchestration services whose task or build role is often over-privileged. Each runs attacker-supplied definition or build steps as the service role.

08Service role → CodeBuild

Create a build project with an admin service role and a buildspec that exfiltrates the role's credentials.

Requires · iam:PassRole + codebuild:CreateProject (+ codebuild:StartBuild)
Detected by audytx · privilege-escalation-capable grant (service-role pass).

09Service role → CodePipeline

Create a pipeline whose stage runs with an admin role, driving escalation through the delivery flow.

Requires · iam:PassRole + codepipeline:CreatePipeline
Detected by audytx · privilege-escalation-capable grant (service-role pass).

10Service role → ECS task definition

Register a task definition that references an admin task role, then run it — the container acts as the role.

Requires · iam:PassRole + ecs:RegisterTaskDefinition
Detected by audytx · privilege-escalation-capable grant; the task-role chain also feeds the ECS attack-path rules.

11Service role → Fargate task

Run a Fargate task with a privileged task role — no ALB or instance needed; the container gets the role directly.

Requires · iam:PassRole + ecs:RunTask (Fargate)
Detected by audytx · privilege-escalation-capable grant; a public-IP Fargate task with an escalation role is raised as a direct attack path.

12Service role → Step Functions

Create a state machine that runs with an admin role, executing steps under those permissions.

Requires · iam:PassRole + states:CreateStateMachine
Detected by audytx · privilege-escalation-capable grant (service-role pass).

13Service role → EventBridge

Create a rule that targets a privileged compute resource, using a passed role to drive it on a schedule or event.

Requires · events:PutRule + iam:PassRole + a privileged target
Detected by audytx · privilege-escalation-capable grant (rule-target role pass).
Group C · Policy attachment and inline policy (7 paths)

The most direct family: if a principal can attach a managed admin policy or write an inline one onto a user, group, or role it controls, it grants itself admin in a single call. All seven are named escalation methods in the Rhino catalog.

14AttachUserPolicy

Attach AdministratorAccess (or any admin managed policy) directly to a user the principal controls.

Requires · iam:AttachUserPolicy
Detected by audytx · privilege-escalation-capable grant (self-admin attach).

15AttachGroupPolicy

Attach an admin policy to a group the principal belongs to, inheriting admin.

Requires · iam:AttachGroupPolicy
Detected by audytx · privilege-escalation-capable grant.

16AttachRolePolicy

Attach an admin policy to a role the principal can assume.

Requires · iam:AttachRolePolicy
Detected by audytx · privilege-escalation-capable grant.

17PutUserPolicy

Write an inline admin policy straight onto a user — no managed policy needed.

Requires · iam:PutUserPolicy
Detected by audytx · privilege-escalation-capable grant (inline admin).

18PutGroupPolicy

Write an inline admin policy onto a group the principal is in.

Requires · iam:PutGroupPolicy
Detected by audytx · privilege-escalation-capable grant (inline admin).

19PutRolePolicy

Write an inline admin policy onto a role the principal can assume.

Requires · iam:PutRolePolicy
Detected by audytx · privilege-escalation-capable grant (inline admin).

20AddUserToGroup

Add the principal's own user to an existing administrator group.

Requires · iam:AddUserToGroup
Detected by audytx · privilege-escalation-capable grant (join admin group).
Group D · Policy-version and credential creation (5 paths)

Escalation that never touches an admin policy by name: rewrite a policy the principal already holds, or mint fresh credentials for another principal that has more access.

21CreatePolicyVersion

Create a new version of a customer-managed policy the principal is already attached to, setting it as default with * permissions.

Requires · iam:CreatePolicyVersion (with SetAsDefault)
Detected by audytx · privilege-escalation-capable grant (policy self-rewrite).

22SetDefaultPolicyVersion

Roll a policy's default pointer back to an older, more permissive version that already exists.

Requires · iam:SetDefaultPolicyVersion
Detected by audytx · privilege-escalation-capable grant (default-version swap).

23CreateAccessKey

Mint a fresh access key for another user that has more privilege, then use it.

Requires · iam:CreateAccessKey on another principal
Detected by audytx · privilege-escalation-capable grant (credential minting).

24CreateLoginProfile

Create a console password for a user that has no login profile yet, then sign in as them.

Requires · iam:CreateLoginProfile on another user
Detected by audytx · privilege-escalation-capable grant (console-access minting).

25UpdateLoginProfile

Reset an existing user's console password to one the attacker knows.

Requires · iam:UpdateLoginProfile on another user
Detected by audytx · privilege-escalation-capable grant (password reset).
Group E · Trust-policy and wildcard grants (3 paths)

Rewrite who may assume a role, or hold a grant so broad it contains admin outright.

26UpdateAssumeRolePolicy

Rewrite a privileged role's trust policy to name the attacker's principal, then assume it. audytx models this against the full trust graph, not the role in isolation.

Requires · iam:UpdateAssumeRolePolicy + sts:AssumeRole
Detected by audytx · privilege-escalation-capable grant; the trust-graph axis reasons about who can then assume the rewritten role.

27AdministratorAccess attach

The blunt case: attaching the AWS-managed AdministratorAccess policy (or an equivalent *:* grant) directly to a principal.

Requires · attach of AdministratorAccess
Detected by audytx · flagged as an admin-equivalent grant on a principal.

28iam:* wildcard

A standalone iam:* grant contains every escalation method above at once — any IAM write becomes reachable.

Requires · iam:* on a principal
Detected by audytx · flagged as a wildcard IAM grant (wildcard-action analysis).
Group F · Infrastructure-mediated (3 paths)

Escalation reached through a resource rather than a bare IAM action — the case single-resource IAM scanners are structurally worst at, because the vulnerable link spans two resources.

29EC2 IMDSv1 SSRF

An internet-reachable instance carrying a privileged profile with IMDSv1 still enabled lets a server-side request forgery read the role's credentials from the metadata endpoint.

Requires · IMDSv1 enabled on an EC2 instance with an escalation instance profile
Detected by audytx · cross-resource attack path (open web port + IMDSv1 + escalation profile) — a Critical when the entry is internet-reachable.

30Secrets Manager exfiltration

An unconstrained secretsmanager:GetSecretValue grant (resource *, no condition) lets a principal read every secret — including credentials for more privileged principals.

Requires · secretsmanager:GetSecretValue on * with no condition
Detected by audytx · credential-exposure grant (unconstrained secret read).

31sts:AssumeRole wildcard

A grant of sts:AssumeRole on resource * lets the principal assume any role whose trust policy allows it — the general case behind role chaining.

Requires · sts:AssumeRole on *
Detected by audytx · privilege-escalation-capable grant; assume targets are resolved against the trust graph.

Why detecting these needs cross-resource reasoning

Most of these paths are invisible to a scanner that judges one resource at a time. The iam:PassRole in path 01 is benign until you see the lambda:CreateFunction beside it and the admin role it points at; the IMDSv1 setting in path 29 is only dangerous because another resource exposes the instance and a third grants it a privileged profile. audytx pre-computes the relationship graph — who can pass which role to what, which principals can assume which roles, what's reachable from the internet — and scores each path against it. That's how it reaches full recall on all 31 while keeping the lowest false-positive count of any tool with full recall in the benchmark: the naive PassRole flags that make other scanners noisy are the ones context proves benign, and audytx suppresses them with the reason shown.

The engine, the trust-graph and attack-path reasoning, and the per-path detection live in the IAM skill; the mechanism is documented on the false-positives page, and the measured recall/precision comparison against Checkov, Trivy, and KICS is on the IAM security page and the benchmark.

Frequently asked questions

How many IAM privilege-escalation paths are there in AWS?

The widely-cited catalog documents 31 paths, drawn from the Rhino Security Labs escalation-methods research and packaged as one Terraform scenario per path in the BishopFox iam-vulnerable corpus. New variants surface as AWS adds services, but these 31 are the standard benchmark set. audytx detects all 31.

What is the iam:PassRole privilege-escalation risk?

iam:PassRole lets a principal hand an existing IAM role to an AWS service. On its own that's a normal, necessary permission — it becomes escalation when the principal can also launch a service that runs code (Lambda, EC2, ECS, Glue, CodeBuild, and more) and pass it a role more privileged than the principal itself. Groups A and B above are all PassRole variants. The fix is to scope PassRole to specific role ARNs, never *.

Does audytx detect all of them in Terraform?

Yes — on the BishopFox iam-vulnerable benchmark audytx reaches full recall across all 31 paths, at the highest precision of any tool that also reaches full recall. The measured comparison (KICS 3%, Trivy 0% on the same corpus) and reproduction steps are on the IAM security page and the benchmark.

How do I prevent IAM privilege escalation?

Scope iam:PassRole to explicit role ARNs; deny the IAM write actions (Attach*/Put*/Create*Policy*/AddUserToGroup) except on break-glass admin principals; enforce IMDSv2 on every instance profile; add conditions to sts:AssumeRole and secret-read grants instead of resource *; and scan Terraform in review so a new path is caught before it merges. audytx flags each of these paths on the pull request that introduces it.

Open beta

Catch these on the pull request

Install the GitHub App and audytx reviews your next Terraform change for every path above — with the chain shown, and the benign PassRole grants suppressed. Free during the beta.