An IAM role can carry up to 10 attached managed policies and exactly one permissions boundary — a limit that matters because that single boundary is often the only thing standing between a delegated developer and full account takeover. AWS's own documentation defines a permissions boundary as a managed policy attached to a user or role that sets the maximum permissions its identity-based policies can grant; it never grants permissions on its own, only caps them. Without one, any principal holding iam:CreateRole, iam:CreatePolicy, and iam:AttachRolePolicy can create a brand-new role, attach AdministratorAccess to it, and assume it — a privilege-escalation path catalogued in detail by Rhino Security Labs' widely-cited "AWS IAM Privilege Escalation" research, which lists dozens of similar IAM misconfiguration routes to full account compromise. AWS published a dedicated Security Blog post, "Delegate permission management to developers by using IAM permissions boundaries," specifically to address this: central cloud teams need to let developers create their own roles and policies without becoming an unbounded escalation vector. This post walks through how the mechanism works, the specific condition key that makes it enforceable, its operational limits, and how to detect when it's been quietly stripped away.
What is an IAM permissions boundary and how does it work?
A permissions boundary is a managed policy — customer-managed or AWS-managed — attached to an IAM user or role that defines the outer limit of what that entity's own identity-based policies are allowed to grant. It is not itself a grant of access. AWS's documentation is explicit that effective permissions are calculated as the intersection of the identity-based policy and the boundary: if the identity policy allows s3:* but the boundary only allows s3:GetObject and s3:ListBucket, the entity can only read and list objects, nothing more. This is different from a permissions policy or a service control policy — a boundary only applies to IAM users and roles, never to groups, and never to resource-based policies like an S3 bucket policy. It exists for exactly one job: capping what a principal can grant to itself or anything it creates, which is why it's the mechanism AWS points to for delegated administration.
What privilege escalation path does a permissions boundary close?
The path it closes is self-escalation through role or user creation. A developer given iam:CreateRole, iam:CreatePolicy, iam:AttachRolePolicy, or iam:PutRolePolicy — permissions that are routine for anyone building CI/CD pipelines or Lambda functions — can, absent a boundary, create a new role, attach a policy granting broad or administrative access, and either assume that role or hand it to a compromised workload. Rhino Security Labs' research on IAM privilege escalation documents this and closely related techniques (such as updating an existing role's assume-role policy or attaching a policy to oneself) as some of the most common real-world misconfigurations found in AWS penetration tests. A permissions boundary breaks this specific chain: even if a developer's identity policy allows iam:CreateRole, any role they create can be forced to inherit a boundary at least as restrictive as their own, so the new role can never grant more than the developer already had.
How do you actually enforce boundaries on delegated administrators?
Enforcement hinges on one condition key: iam:PermissionsBoundary. A delegated-admin policy should grant iam:CreateRole, iam:CreateUser, and iam:PutRolePolicy only when the request includes a Condition block requiring iam:PermissionsBoundary to equal a specific boundary ARN (or one from an approved set). Without that condition, granting iam:CreateRole to a developer — even alongside a boundary on the developer's own identity — does nothing to constrain roles they subsequently create, because a boundary does not automatically propagate to resources an entity provisions. This is the failure mode called out repeatedly in AWS and third-party practitioner guidance: teams assume "the developer is bounded, so what they create is bounded," when in fact the API call itself must carry the condition or the created role starts unbounded. The pattern also typically denies iam:DeleteRolePermissionsBoundary and blocks attaching or modifying the boundary policy itself, so a delegated admin can create and manage roles freely within the lane, but can't widen the lane.
What are the operational limits teams run into?
AWS enforces a hard structural limit relevant here: an IAM user or role can have at most 10 attached managed policies plus exactly one permissions boundary — you cannot stack multiple boundaries to layer restrictions, so the single boundary policy has to encode the full ceiling for that entity in one document. Boundaries also only attach to users and roles, not to groups or resource-based policies, so a delegation model built around IAM groups needs a different enforcement layer (typically service control policies at the AWS Organizations level) to cover the group-based half of the access model. A recurring practical mistake is writing an overly permissive boundary "just to get delegation working" and never tightening it — since the boundary is a ceiling, not a floor, a boundary that's too generous provides no real protection even though it's technically present on every entity.
How do you detect when a boundary has been removed or weakened?
Because a stripped boundary silently restores whatever an identity policy already allows, detection has to focus on the removal event itself, not on scanning current state alone. CloudTrail logs every iam:DeleteRolePermissionsBoundary, iam:PutRolePermissionsBoundary, and iam:PutUserPermissionsBoundary call, and these are exactly the events security teams should alert on in near-real time, since a legitimate boundary change is rare and a delegated admin removing their own boundary is close to always adversarial or a serious misconfiguration. IAM Access Analyzer complements this by continuously evaluating whether an entity's effective permissions have expanded beyond an intended baseline, catching drift that a point-in-time policy review would miss. The combination — deny-by-default IAM policies that block boundary modification, plus CloudTrail alerting on the handful of API calls that could remove one anyway — is what turns permissions boundaries from a paper control into one that actually holds under a compromised or careless delegated-admin account.