Skip to main content

Command Palette

Search for a command to run...

iam:PassRole Explained: The Most Abused IAM Permission

Updated
2 min read
S
AI-Powered security analysis for AWS IAM policies, CloudFormation templates, and costs. Web app + CLI + VS Code extension + GitHub Action + CDK Guard. Try free at shieldly.io

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.

On Resource: * — meaning 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. It is a skeleton key.

Why It Leads to Privilege Escalation

The escalation is indirect. An attacker creates a compute resource and attaches an admin-level role to it, then invokes that resource and uses its credentials. From CloudTrail's perspective the action that produced the admin credentials was a lambda:InvokeFunction, not an IAM write.

The Dangerous Combinations

PassRole + RunInstances. Lets an attacker launch an instance with an administrator instance profile and immediately harvest credentials via IMDS.

PassRole + Lambda. Deploy a function attached to a privileged execution role and run arbitrary AWS SDK calls through it.

PassRole + ECS or Glue. Same pattern — both accept an execution role and can run attacker-controlled code under that role's permissions.

How to Scope iam:PassRole Safely

Lock PassRole along two axes: the specific role ARNs that can be passed, and the service that is allowed to receive them. Use the iam:PassedToService condition key.

Resource: arn:aws:iam::123456789012:role/my-lambda-role with Condition: iam:PassedToService: lambda.amazonaws.com

Originally published at shieldly.io/blog. Catch iam:PassRole risks at shieldly.io/app/iam.