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 security · Terraform · attack-path reasoning

AWS IAM privilege escalation detection in Terraform

Most IaC scanners check IAM resources in isolation — single-resource pattern matching against one policy file at a time. audytx builds an effective-permission graph across your Terraform, resolves who can assume each role, and traces iam:PassRole grants and AssumeRole role chaining to find privilege-escalation paths by reachability. The verdict comes from that graph: deterministic and hand-written — identical input, identical findings, no model in the loop. On the BishopFox iam-vulnerable corpus that means full recall on the 31 documented paths at the highest precision of any tool with full recall.

iam:PassRole chains AssumeRole role chaining trust-policy analysis wildcard expansion effective-permission graph end-to-end attack paths
31
documented IAM escalation paths — every one detected
100%
recall on the BishopFox iam-vulnerable corpus
IAM precision vs the next tool with full recall
0
verdicts from a guessed value — fully deterministic
The problem

What IAM privilege escalation is in Terraform

A principal with limited permissions grants itself more by chaining API calls: attach a policy, assume another role, or pass a privileged role to a service. In Terraform the chain is visible across the configuration — a policy grants iam:PassRole, a function references that role, a trust policy lets the principal assume it — so detecting it means reading all three together.

Pattern-matching scanner

Flags each resource against a checklist: "this policy has iam:PassRole." Without the chain it faces a false choice — stay quiet and miss the path (KICS: 3% recall, Trivy: 0%), or flag every occurrence and drown the review (Checkov: 238 false positives to reach the same 31 paths).

audytx: graph reachability

  • Expands wildcard actions (iam:*, lambda:*) to concrete permissions
  • Runs trust policy analysis: who can assume each role?
  • Walks AssumeRole and PassRole chains across the resource graph
  • Flags the full chain: source principal → escalation vector → elevated permissions
Coverage

All 31 documented IAM privilege-escalation paths, detected

The BishopFox iam-vulnerable corpus documents 31 AWS IAM privilege-escalation paths, one Terraform file per path. audytx detects every one — grouped here by escalation vector. For a path-by-path reference — the exact IAM actions each one needs, cited to AWS, with a mitigation for each — see the full privilege-escalation guide.

PassRole → service AssumeRole chaining direct privilege wildcard / admin attach service-role escalation EC2 IMDS SSRF secrets exfiltration STS wildcard
PassRole → Lambda
CreateFunction + InvokeFunction
iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction
PassRole → EC2
EC2 instance with privileged profile
iam:PassRole + ec2:RunInstances
PassRole → CloudFormation
Stack creation with admin role
iam:PassRole + cloudformation:CreateStack
PassRole → Glue
Glue job with admin role
iam:PassRole + glue:CreateJob + glue:StartJobRun
Direct privilege
CreateNewPolicyVersion
iam:CreatePolicyVersion
Direct privilege
SetDefaultPolicyVersion
iam:SetDefaultPolicyVersion
Direct privilege
CreateAccessKey
iam:CreateAccessKey on other principals
Direct privilege
CreateLoginProfile
iam:CreateLoginProfile on other users
Direct privilege
UpdateLoginProfile
iam:UpdateLoginProfile → console access
AssumeRole chain
AttachUserPolicy
iam:AttachUserPolicy → AdministratorAccess
AssumeRole chain
AttachGroupPolicy
iam:AttachGroupPolicy → AdministratorAccess
AssumeRole chain
AttachRolePolicy
iam:AttachRolePolicy → AdministratorAccess
AssumeRole chain
PutUserPolicy
iam:PutUserPolicy → inline admin policy
AssumeRole chain
PutGroupPolicy
iam:PutGroupPolicy → inline admin policy
AssumeRole chain
PutRolePolicy
iam:PutRolePolicy → inline admin policy
AssumeRole chain
AddUserToGroup
iam:AddUserToGroup → admin group
AssumeRole chain
UpdateAssumeRolePolicy
iam:UpdateAssumeRolePolicy → assume privileged role
PassRole → SSM
SSM Send Command
ssm:SendCommand on EC2 with admin profile
PassRole → DataPipeline
Data Pipeline activation
iam:PassRole + datapipeline:CreatePipeline
PassRole → SageMaker
SageMaker training job
iam:PassRole + sagemaker:CreateTrainingJob
EC2 SSRF
EC2 IMDS v1 exposure
IMDSv1 on EC2 with instance profile → metadata SSRF
Wildcard
AdministratorAccess direct attach
iam:* or AdministratorAccess on a principal
Wildcard
IAM full access
iam:* as standalone permission
Service role
CodeBuild role with admin pass
iam:PassRole → CodeBuild project
Service role
CodePipeline admin escalation
iam:PassRole → CodePipeline with admin stage
Service role
ECS task definition with admin role
iam:PassRole + ecs:RegisterTaskDefinition
Service role
Fargate task escalation
iam:PassRole + ecs:RunTask (Fargate)
Service role
StepFunctions admin role
iam:PassRole + states:CreateStateMachine
Service role
EventBridge rule → Lambda admin
events:PutRule + iam:PassRole + privileged target
Secrets exfil
Secrets Manager unrestricted read
secretsmanager:GetSecretValue without resource constraint
STS
sts:AssumeRole wildcard
sts:AssumeRole on * resource
Measured

Benchmark: audytx vs Checkov, Trivy, KICS on iam-vulnerable

Same corpus, same 100% recall — half the alert volume of Checkov and twice the IAM precision.

100%
Recall — all 31 documented paths detected
Checkov also 100% · KICS 3% · Trivy 0%
IAM precision vs Checkov
23% vs 12% at same 100% recall
½
Alert volume vs Checkov
135 HIGH findings vs 269
ToolHIGH findingsTP (paths)FPPrecisionRecall
audytx1353110423%100%
Checkov2693123812%100%
KICS91811%3%
Trivy7070%0%

Corpus: BishopFox iam-vulnerable · 31 documented paths · one Terraform file per path. Full methodology and raw data: audytx benchmark page.

Open beta

Start free during the open beta

Install audytx on one repo. The next pull request that touches IAM gets the full attack-path analysis — iam:PassRole chains, role chaining, trust-policy and wildcard reasoning — right in the review comment.

Worked example

A worked example: PassRole privilege escalation in Terraform

How three Terraform files create an IAM privilege-escalation path that single-resource pattern matching can't prove.

The setup: A developer role with limited permissions, a Lambda function, and an admin role. The Lambda can be invoked by the developer. The developer has iam:PassRole on the admin role. Single-resource scanners either stay quiet or flag the bare iam:PassRole grant without proving where it leads. audytx reads the chain and reports the full path.
# iam_role_developer.tf
resource "aws_iam_role" "developer" {
  name = "developer-role"
}

resource "aws_iam_role_policy" "developer_policy" {
  role = aws_iam_role.developer.id
  policy = jsonencode({
    Statement = [{
      Effect   = "Allow"
      Action   = ["lambda:InvokeFunction", "iam:PassRole"]
      Resource = "*"
    }]
  })
}
# lambda.tf
resource "aws_lambda_function" "updater" {
  function_name = "config-updater"
  role          = aws_iam_role.admin.arn  # ← receives the passed role
}

resource "aws_iam_role" "admin" {
  name = "admin-role"
}

resource "aws_iam_role_policy_attachment" "admin_policy" {
  role       = aws_iam_role.admin.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
audytx finding: [CRIT] ATTACK_PATH_SEARCH — aws_iam_role.developer has iam:PassRole on aws_iam_role.admin (AdministratorAccess). Principal can invoke aws_lambda_function.updater to execute arbitrary code with admin permissions. Privilege-escalation path: developer → PassRole → admin → AdministratorAccess.

A pattern matcher scanning only iam_role_policy sees iam:PassRole as a potential concern but can't confirm the target role is privileged without reading iam_role_policy_attachment. audytx resolves the full chain across all three resources.

What it checks

IAM security checks in audytx

Direct misconfigurations and cross-resource attack paths. A verdict never rests on a guessed value — data the configuration doesn't supply is reported as unverifiable (Incomplete), not assumed.

ATTACK_PATH_SEARCH

Graph-reachability search across roles, policies, trust relationships, and services. Finds iam:PassRole chains, AssumeRole role chaining, and service-linked escalation vectors.

Effective-permission expansion

Wildcards (iam:*, *) are expanded to concrete actions before reasoning. A principal with iam:* gets the same treatment as one with every individual IAM action listed.

Trust policy analysis

Who can assume each role? audytx checks both the principal list and aws:PrincipalAccount conditions — a cross-account trust to * is treated differently from a same-account service trust.

Context suppression

Not every high-privilege role is a finding. An admin role used only by a known-safe service with a narrowly-scoped trust policy may be suppressed, with the reasoning shown in the PR comment.

See the full IAM check inventory on the features page and the raw benchmark data on the comparison page.

FAQ

IAM privilege escalation: common questions

What is IAM privilege escalation in Terraform?

IAM privilege escalation happens when a principal with limited permissions grants itself more by chaining API calls — attaching a policy, assuming another role, or passing a privileged role to a service like Lambda or EC2. In Terraform these chains are visible across the configuration if you read the resources together.

Can Terraform scanners detect privilege escalation?

Single-resource pattern matchers struggle. Without following the chain they either stay quiet and miss the path, or flag every occurrence and drown the review in false positives. audytx builds an effective-permission graph and traces reachability across roles, policies, and trust relationships to prove the full path instead.

How does audytx detect iam:PassRole chains?

audytx builds an effective-permission graph across the whole Terraform configuration, expands wildcard actions to concrete permissions, and resolves trust policies to learn who can assume each role. It then walks PassRole and AssumeRole chains across the resource graph, reporting the full path from source principal to elevated permissions.

See IAM findings on your next PR

Install audytx on one repo. The next PR that touches IAM gets the full attack-path analysis in the review comment: iam:PassRole chains, role chaining, trust policy analysis, wildcard expansion.

Install audytx free →

Or use the MCP server: claude mcp add --transport http audytx https://audytx.com/mcp