DEV Community

Jeff Tham
Jeff Tham

Posted on • Originally published at shieldly.io

iam:PassRole Explained: The Most Abused IAM Permission

Originally published at shieldly.io/blog.

Of all the IAM permissions that appear in misconfigured AWS accounts, iam:PassRole is the one security teams most consistently underestimate. It does not give a principal admin rights on its own. It does something more subtle: it lets a principal hand a role to an AWS service.

What iam:PassRole Actually Does

When you launch an EC2 instance with an instance profile, create a Lambda function with an execution role, or start an ECS task with a task role — you are passing an IAM role to an AWS service. AWS requires the calling identity to hold iam:PassRole on the target role before it can hand that role to a service.

{
  "Effect": "Allow",
  "Action": "iam:PassRole",
  "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

On Resource: *, the holder can pass any role in the account to any service — including roles with administrator-level permissions. iam:PassRole is not a narrow delegation control here. It is a skeleton key.

Why It Leads to Privilege Escalation

The escalation is indirect. An attacker with iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction:

  1. Creates a Lambda function and attaches an admin-level execution role
  2. Invokes the function with code that calls iam:CreateUser or sts:AssumeRole
  3. Gets admin-level AWS SDK access from inside the function

From CloudTrail's perspective, the action that produced the admin credentials was a lambda:InvokeFunction — not an IAM write. It's easy to miss in a post-incident review.

The Dangerous Combinations

PassRole + ec2:RunInstances — launch an instance with an administrator instance profile, harvest credentials from IMDSv1 immediately.

PassRole + lambda:CreateFunction — deploy a function with a privileged execution role, run arbitrary AWS SDK calls through it.

PassRole + ecs:RegisterTaskDefinition / glue:CreateJob — both accept execution roles and run attacker-controlled code.

How to Scope iam:PassRole Safely

Lock PassRole along two axes:

  1. Specific role ARNs that can be passed (the Resource element)
  2. The service allowed to receive them (the iam:PassedToService condition key)
{
  "Effect": "Allow",
  "Action": "iam:PassRole",
  "Resource": "arn:aws:iam::123456789012:role/my-lambda-execution-role",
  "Condition": {
    "StringEquals": {
      "iam:PassedToService": "lambda.amazonaws.com"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This allows passing exactly one role, only to Lambda. Any other role or any other service is denied.


Catch iam:PassRole risks automatically — paste a policy into Shieldly's free AI-Powered analysis. No signup, no credit card.

Launch offer: code 90Off2M — 90% off first 2 months. Pro from $1.90/mo. shieldly.io/pricing

Top comments (0)