Skip to main content
cd ../config-traps
risk/register/unscoped-iam-passrole-lambda-admin-escalation.html
AWS IAM Privilege Escalationcritical severityAmazon Web Services

Unscoped iam:PassRole Grants Let Lambda Deploy Roles Escalate to Admin Access

Severity
critical
Reviewed
5 Aug 2026
Remediation
~20 minutes
Overview

A wildcard iam:PassRole grant lets an AWS Lambda deploy identity pass any role, including privileged ones, to a function it controls — a quiet path to full account escalation.

Operational summary

At a glance

Symptom
CloudTrail shows a deployment identity — one whose declared job is publishing AWS Lambda functions — performing actions well outside that scope, such as…
Likely cause
An unscoped iam:PassRole statement, combined with permission to create or update a compute resource such as a Lambda function, lets the deploy identity pass…
Impact
Any identity that can reach this combination of permissions can escalate to the privilege level of the most powerful role reachable through PassRole, up to full account administration.
Verification signal
Re-test the exact paths used during diagnosis and confirm they now fail closed rather than assuming the fix worked.Re-run aws iam simulate-principal-policy for iam:PassRole against the previously reachable…
Safe correction
Replace the wildcard grant with a statement naming the specific role ARNs the deploy identity is permitted to pass, and add an iam:PassedToService condition restricting the grant to…
Rollback or recovery
If the scoped policy blocks a legitimate deployment, restore the previous policy version rather than reintroducing the wildcard grant.Identify the prior version with aws iam list-policy-versions --policy-arn .Restore…

Symptom

CloudTrail shows a deployment identity — one whose declared job is publishing AWS Lambda functions — performing actions well outside that scope, such as modifying S3 bucket policies, creating IAM users or reading secrets in other services. No policy directly attached to the deploy identity grants those permissions, so a review of its own attached policies finds nothing wrong.

The identity’s IAM policy still looks minimal and reasonable on paper: permission to manage Lambda functions, plus a broad iam:PassRole statement that the team added months earlier so deployments would not keep failing on role-assignment errors.

False Assumption

The review treats the wildcard iam:PassRole statement, scoped as Resource: "*", as low risk because it reasons that PassRole only lets the identity hand an existing role to a resource — it does not itself grant the permissions contained in that role. Since no broad managed policy such as AdministratorAccess is attached directly to the deploy identity, the wildcard grant is waved through as a convenience fix rather than a privilege boundary.

Root Cause

An unscoped iam:PassRole statement, combined with permission to create or update a compute resource such as a Lambda function, lets the deploy identity pass any role in the account — including roles with far greater privilege than the deploy identity itself — to that resource. Once the function runs under the passed role, code invoked through it executes with that role’s permissions, not the deploy identity’s own permissions. The escalation path never touches the deploy identity’s attached policy, so a policy review that only inspects the suspect identity’s own statements will not surface it.

Impact

Any identity that can reach this combination of permissions can escalate to the privilege level of the most powerful role reachable through PassRole, up to full account administration. Because the escalation happens through resource creation rather than a policy change, it produces CloudTrail events that look like ordinary deployment activity unless the reviewer specifically correlates PassRole calls against the role ARNs they target.

Diagnosis

Confirm the exposure before changing anything.

  • Export the account’s IAM policy set with aws iam get-account-authorization-details and search for iam:PassRole statements using Resource: "*" or omitting an iam:PassedToService condition.
  • Use aws iam simulate-principal-policy to test, against the ARN of a specific highly privileged role, whether the deploy identity is currently permitted to pass it.
  • Cross-reference CloudTrail PassRole events issued by the deploy identity against CreateFunction, UpdateFunctionConfiguration or RunInstances events targeting role ARNs outside the identity’s intended scope.

Correction

Replace the wildcard grant with a statement naming the specific role ARNs the deploy identity is permitted to pass, and add an iam:PassedToService condition restricting the grant to the intended service.

{
  "Effect": "Allow",
  "Action": "iam:PassRole",
  "Resource": "arn:aws:iam::ACCOUNT_ID:role/lambda-deploy-execution-role",
  "Condition": {
    "StringEquals": { "iam:PassedToService": "lambda.amazonaws.com" }
  }
}

Apply the scoped statement as a new managed-policy version rather than editing the existing version in place, so the previous version remains available if a legitimate deployment breaks.

Validation

Re-test the exact paths used during diagnosis and confirm they now fail closed rather than assuming the fix worked.

  • Re-run aws iam simulate-principal-policy for iam:PassRole against the previously reachable privileged role ARN and confirm the result changes from allowed to denied.
  • In an isolated or non-production account, attempt to create a Lambda function passing the previously reachable role and confirm the call fails with AccessDenied referencing iam:PassRole.
  • Review CloudTrail for the deploy role over the following 24 hours and confirm no PassRole events target role ARNs outside the new allow-list.

Rollback

If the scoped policy blocks a legitimate deployment, restore the previous policy version rather than reintroducing the wildcard grant.

  • Identify the prior version with aws iam list-policy-versions --policy-arn <deploy-policy-arn>.
  • Restore it with aws iam set-default-policy-version-id --policy-arn <deploy-policy-arn> --version-id <previous-version-id>.
  • Add the missing legitimate role ARN to the scoped allow-list and re-apply the fix rather than leaving the wildcard restored.

Prevention

Treat every iam:PassRole grant as carrying the risk of the most privileged role it can reach, and scope it during policy review rather than inspecting only the identity’s own attached permissions. Pair scoped PassRole statements with a permission boundary on deploy roles and a periodic export via get-account-authorization-details so wildcard grants introduced as quick fixes are caught before the next incident rather than after it. AWS’s Well-Architected Security Pillar documents design principles and operational practices for protecting AWS workloads, including applying least-privilege access as a routine review discipline rather than a one-off remediation; incorporate PassRole scoping checks into that recurring review cycle.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

iam:PassRole
Resource: "*"
PassRole
04

Verify, roll back or escalate

Verify

Re-test the exact paths used during diagnosis and confirm they now fail closed rather than assuming the fix worked.Re-run aws iam simulate-principal-policy for iam:PassRole against the previously reachable privileged role ARN and confirm the result changes from allowed to denied.In…

Rollback

If the scoped policy blocks a legitimate deployment, restore the previous policy version rather than reintroducing the wildcard grant.Identify the prior version with aws iam list-policy-versions --policy-arn <deploy-policy-arn>.Restore it with aws iam set-default-policy-version-id --policy-arn <deploy-policy-arn> --version-id <previous-version-id>.Add the missing legitimate…

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources