AWS IAM privilege escalation detection in Terraform
Many IaC checks look at one IAM resource at a time. audytx also 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 engine is deterministic and
hand-written — identical input, identical findings, no model in the loop. On the
BishopFox iam-vulnerable corpus it detected all 31 documented paths in
our last measured run (engine 1.18.276, 2026-08-07).
iam:PassRole chains
AssumeRole role chaining
trust-policy analysis
wildcard matching
effective-permission graph
end-to-end attack paths
iam-vulnerable corpus, measured 2026-08-07What 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.
Checking one resource at a time
Flags each resource against a checklist: "this policy has iam:PassRole." Without the chain it faces a choice — stay quiet and miss the path, or flag every occurrence and add noise to the review.
audytx: graph reachability
- Matches wildcard actions (
iam:*,lambda:*) against the permissions they cover - Runs trust policy analysis: who can assume each role?
- Walks
AssumeRoleandPassRolechains across the resource graph - Reports the chain where it can be traced: source principal → escalation vector → elevated permissions
The 31 iam-vulnerable paths, detected
The BishopFox iam-vulnerable corpus documents 31 AWS IAM privilege-escalation paths, one Terraform file per path. audytx detected every one in the last measured run (engine 1.18.276, 2026-08-07) — grouped here by the upstream categories. For the actions each policy grants, see the path table.
Our result on iam-vulnerable
All 31 documented paths detected in the last measured run. The result is dated and is not re-measured on every release.
Corpus: BishopFox iam-vulnerable · 31 documented paths · one Terraform file per path.
Start free
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.
A worked example: PassRole in Terraform
Two Terraform files and the findings audytx reported for them.
iam:PassRole and lambda:InvokeFunction on all resources, a Lambda function, and an admin role (trusted by Lambda) with the AWS-managed AdministratorAccess policy attached.
# iam_role_developer.tf
resource "aws_iam_role" "developer" {
name = "developer-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "sts:AssumeRole"
Principal = { Service = "ec2.amazonaws.com" }
}]
})
}
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"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "sts:AssumeRole"
Principal = { Service = "lambda.amazonaws.com" }
}]
})
}
resource "aws_iam_role_policy_attachment" "admin_policy" {
role = aws_iam_role.admin.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
[HIGH] AWS_IAM_020· iam_role_developer.tf ·developer_policy
IAM policy developer_policy: enables privilege escalation — pass any role to a compute service — granted on an unconstrained resource (Resource: "*") with no Condition. Any principal holding this policy can escalate to broader or administrator privileges.[HIGH] AWS_IAM_021· iam_role_developer.tf ·aws_iam_role.developer
Toxic combination on role developer: it is assumable by a compute service (EC2 / ECS / Lambda), AND its attached policies grant pass any role to a compute service. An attacker who compromises that workload (SSRF, RCE, dependency takeover) can steal the instance/task role credentials and obtain those permissions. Neither the trust policy nor the permission policy is flagged in isolation — the risk is the path between them.[HIGH] AWS_IAM_021· lambda.tf ·aws_iam_role.admin
Toxic combination on role admin: it is assumable by a compute service (EC2 / ECS / Lambda), AND its attached policies grant full administrator wildcard (Action: "*"). An attacker who compromises that workload (SSRF, RCE, dependency takeover) can steal the instance/task role credentials and obtain those permissions. Neither the trust policy nor the permission policy is flagged in isolation — the risk is the path between them.[CRITICAL] AWS_OPS_036· lambda.tf ·aws_iam_role_policy_attachment.admin_policy
admin_policy: a full-privilege AWS-managed policy (AdministratorAccess or IAMFullAccess) is attached. AdministratorAccess grants unrestricted access to every service; IAMFullAccess grants full IAM control, which can be used to attach AdministratorAccess to any principal and escalate to full account control.
The scan also returned lower-severity findings on these files, which are not shown. The two AWS_IAM_021 findings are the cross-resource ones: each combines a role's trust policy with the permissions attached to it.
IAM security checks in audytx
Direct misconfigurations and cross-resource attack paths. Data the configuration
doesn't supply is reported as Incomplete, not assumed.
IAM privilege-escalation checks
Reachability across roles, policies, trust relationships, and services. Finds iam:PassRole chains, AssumeRole role chaining, and service-linked escalation vectors.
Effective-permission matching
Wildcards (iam:*, *) are matched against the actions they cover. 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 reads each role's trust policy — a cross-account trust to * is treated differently from a same-account service trust.
Context suppression
Findings that other resources show to be harmless are held back, with the reason shown.
See the full IAM check inventory on the features page.
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?
Checks that look at one resource at a time have to either stay quiet and miss the path, or flag every occurrence and add noise to the review. audytx builds an effective-permission graph and traces reachability across roles, policies, and trust relationships to follow the path instead.
How does audytx detect iam:PassRole chains?
audytx builds an effective-permission graph across the whole Terraform configuration, matches wildcard actions against the permissions they cover, and resolves trust policies to learn who can assume each role. It then follows PassRole and AssumeRole chains across the resource graph and reports what it can trace 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 matching.
Install audytx free →Or use the MCP server: claude mcp add --transport http audytx https://audytx.com/mcp --header "X-Client-ID: YOUR_CLIENT_ID"