AWS IAM privilege escalation detection in Terraform
Most IaC scanners check IAM resources in isolation — matching wildcard actions
in a single policy file. audytx builds an effective-permission graph across all
your Terraform resources and walks AssumeRole / PassRole
chains to find privilege-escalation paths by reachability, not by a
hand-written pattern. It detects all 31 documented IAM privesc paths on the
BishopFox iam-vulnerable corpus — the only other tool that does
is Checkov.
What IAM privilege escalation is in Terraform
IAM privilege escalation happens when a principal with limited permissions can
acquire additional privileges by chaining a sequence of API calls — attaching a
policy, assuming a role, passing a role to a service, or calling a privileged
service like Lambda or EC2. In Terraform, these chains are
visible in the configuration: an aws_iam_role_policy
grants iam:PassRole, an aws_lambda_function references
that role, and a trust policy allows the principal to assume it. Detecting the path
requires reading all three resources together.
Pattern-matching scanner
Flags each resource against a checklist: "this policy has iam:PassRole." Misses chains that only become privesc when combined — 25+ of the 31 paths require reading two or more resources.
audytx — graph reachability
- Expands wildcard actions (
iam:*,lambda:*) to concrete permissions - Resolves trust policies — who can assume this role?
- Walks
AssumeRoleandPassRolechains across the resource graph - Flags the full chain: source principal → escalation vector → elevated permissions
The 31 documented IAM privilege-escalation paths — all detected
From the BishopFox iam-vulnerable corpus — 31 documented AWS IAM privilege-escalation paths, one Terraform file per path. audytx detects all 31. Organized below by escalation vector.
Benchmark: audytx vs Checkov, Trivy, KICS on iam-vulnerable
| Tool | HIGH findings | TP (paths) | FP | Precision | Recall |
|---|---|---|---|---|---|
| audytx | 135 | 31 | 104 | 23% | 100% |
| Checkov | 269 | 31 | 238 | 12% | 100% |
| KICS | 9 | 1 | 8 | 11% | 3% |
| Trivy | 7 | 0 | 7 | 0% | 0% |
Corpus: BishopFox iam-vulnerable · 31 documented paths · one Terraform file per path. Full methodology and raw data: audytx benchmark page.
A worked example: PassRole privilege escalation in Terraform
How a three-file configuration creates an IAM privilege-escalation path that pattern matching misses.
iam:PassRole on the admin role. Single-resource scanners see three separate files — none flagged. audytx reads the chain.
# 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"
}
[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.
IAM security rules in audytx
audytx's IAM engine covers both direct misconfigurations and cross-resource attack paths.
Rules fire when the configuration provides enough information to reason about them —
missing attributes produce Incomplete (no false alarm from partial config).
Graph-reachability search across all roles, policies, trust relationships, and services. Finds PassRole chains, AssumeRole traversal, and service-linked escalation vectors.
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.
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.
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 rule inventory on the features page and the raw benchmark data on the comparison page.
See IAM findings on your next PR
Install audytx on one repo. The next PR that touches an IAM resource gets the full attack-path analysis — PassRole chains, AssumeRole traversal, wildcard expansion — in the PR comment.
Install audytx free →Or use the MCP server: claude mcp add --transport http audytx https://audytx.com/mcp