Security Risks of iam:PassRole and How to Properly Restrict It in IAM Policies
Granting iam:PassRole with Resource: "*" creates a privilege escalation vector that allows principals to assume any attachable IAM role through AWS compute services.
The iam:PassRole permission lets principals hand off IAM roles to AWS services like EC2, Lambda, and Step Functions, but when overly broad, it enables attackers to inherit administrative privileges. According to the aws/agent-toolkit-for-aws repository, properly restricting this permission requires scoping resources to specific ARNs and leveraging condition keys to bind roles to intended services. This guide covers the security risks and implementation patterns found in the repository's IAM skill documentation.
Why iam:PassRole Creates Privilege Escalation Risks
When a principal possesses iam:PassRole permissions, they can cause AWS services to assume IAM roles on their behalf. This creates several critical attack vectors documented in skills/core-skills/aws-iam/SKILL.md and plugins/aws-core/skills/aws-iam/SKILL.md.
The Wildcard Resource Problem
Using "Resource": "*" with iam:PassRole allows a principal to pass any role in the account, including highly privileged administrator roles. When combined with permissions to launch EC2 instances or create Lambda functions, this effectively grants the principal the ability to assume any role that can be attached to those services.
Cross-Account Abuse Potential
If a role ARN from another AWS account is passable, an attacker can gain access to resources in external accounts. The repository notes that cross-account PassRole permissions without account-based conditions (aws:PrincipalAccount) create lateral movement opportunities across organizational boundaries.
How to Restrict iam:PassRole Using Least-Privilege Patterns
The repository's IAM skill files provide specific patterns for implementing least-privilege PassRole permissions across multiple AWS services.
Scope Resources to Specific Role ARNs
Never use wildcard resources. Instead, enumerate exact role ARNs that the principal needs to pass:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"arn:aws:iam::123456789012:role/lambdaExecutionRole"
]
}
Leverage Condition Keys for Service Restrictions
Use the iam:PassedToService condition key to limit which service can receive the passed role. This prevents role misuse across unintended services:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ecs.amazonaws.com"
}
}
}
Additional condition keys include iam:AssociatedResourceArn for tying roles to specific resources and aws:PrincipalAccount for cross-account restrictions.
Combine with Service-Specific API Permissions
Only grant PassRole when the principal also needs to invoke the service API that consumes the role. This reduces blast radius if the principal's credentials are compromised:
{
"Effect": "Allow",
"Action": [
"ecs:RegisterTaskDefinition",
"iam:PassRole"
],
"Resource": [
"arn:aws:ecs:us-east-1:123456789012:task-definition/my-app:*",
"arn:aws:iam::123456789012:role/ecsTaskExecutionRole"
],
"Condition": {
"StringEquals": {
"iam:PassedToService": "ecs.amazonaws.com"
}
}
}
Practical IAM Policy Examples
The repository provides concrete implementations in skills/specialized-skills/serverless-skills/processing-s3-uploads-with-step-functions/references/iam-roles.md and plugins/aws-core/skills/aws-containers/references/task-definition-authoring.md.
Restricting PassRole for Lambda Functions
Limit PassRole to specific Lambda execution roles and bind them to the Lambda service:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLambdaToPassExecutionRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/MyLambdaExecRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
},
{
"Sid": "AllowCreateLambda",
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:UpdateFunctionConfiguration"
],
"Resource": "*"
}
]
}
Step Functions and ECS Task Roles
When Step Functions launches ECS tasks, both the Step Functions role and the ECS task role require iam:PassRole. Restrict the ECS task role as follows:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::123456789012:role/EcsTaskRole",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ecs-tasks.amazonaws.com"
}
}
}
Cross-Account Role Restrictions
For scenarios requiring cross-account role passing, restrict by principal account:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::111122223333:role/SharedReadOnlyRole",
"Condition": {
"StringEquals": {
"aws:PrincipalAccount": "123456789012"
}
}
}
Key Repository References
The aws/agent-toolkit-for-aws repository contains authoritative guidance in these locations:
skills/core-skills/aws-iam/SKILL.md: Core guidance oniam:PassRolerisks, least-privilege patterns, and condition key usage.plugins/aws-core/skills/aws-iam/SKILL.md: Plugin-layer duplicate of the core IAM security guidance.skills/specialized-skills/serverless-skills/processing-s3-uploads-with-step-functions/references/iam-roles.md: Concrete IAM role definitions for Step Functions workflows, including requiredPassRoleactions.plugins/aws-core/skills/aws-containers/references/task-definition-authoring.md: ECS-specificPassRolerequirements for task definitions.
Summary
- Never grant
iam:PassRoleon*; always enumerate specific role ARNs that principals need to pass. - Leverage condition keys (
iam:PassedToService,iam:AssociatedResourceArn,aws:PrincipalAccount) to bind permissions to specific services or accounts. - Pair
PassRolewith service actions that actually require the role, such asecs:RegisterTaskDefinitionorlambda:CreateFunction. - Restrict role trust policies independently so that even if a role is passed, only intended principals can assume it.
- Consult the repository's IAM skill documentation when drafting new policies to ensure alignment with AWS security best practices.
Frequently Asked Questions
What makes iam:PassRole a security risk?
iam:PassRole becomes dangerous when granted with wildcard resources ("*"), allowing principals to pass any IAM role—including administrator roles—to AWS services they can invoke. This creates a privilege escalation path where a user with limited permissions can effectively assume highly privileged roles by launching compute resources like EC2 instances or Lambda functions.
How do I restrict iam:PassRole to specific services?
Use the StringEquals condition with the iam:PassedToService key to specify the exact service endpoint that can receive the role. For example, "iam:PassedToService": "ecs.amazonaws.com" ensures the role can only be passed to ECS, preventing misuse by Lambda, Step Functions, or other services even if the principal has broader permissions.
Can I use wildcards in iam:PassRole resource ARNs?
While technically possible, the repository explicitly warns against using wildcards in iam:PassRole resource fields. Instead, list explicit role ARNs or use path-based ARN patterns with appropriate naming conventions. Never use "Resource": "*" with iam:PassRole in production environments, as this violates the principle of least privilege and creates audit findings.
How does iam:PassRole relate to role trust policies?
iam:PassRole controls which principals can hand a role to a service, while the role's trust policy (assume role policy) controls which entities can actually assume the role. Both must be restricted: even if you properly limit PassRole permissions, a permissive trust policy ("Principal": "*") on the target role still allows unauthorized assumption. Secure implementations require tightening both the PassRole IAM policy and the target role's trust relationships.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →