Permissions boundaries and service control policies (SCPs) both cap AWS permissions without granting any, so teams often pick one and assume it covers the job of the other, leaving gaps an attacker with one leaked key can walk through. A permissions boundary caps one IAM user or role. An SCP caps every principal in a member account. A resource control policy (RCP) caps what any principal, including one outside your organisation, can do to resources in a member account. Each stops different things, each has its own blind spots, and the effective permission for any request is the intersection of all of them. This guide is for cloud security and platform teams deciding which guardrail to use for which risk, and how they combine during evaluation. It assumes you know the basics: for boundary design see the AWS IAM Permissions Boundaries Guide, and for SCP design see the AWS Organizations and SCPs Guide.
This is an independent guide from NHI Mgmt Group, based on AWS's public documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.
Key takeaways
- Different scopes, same ceiling logic. A boundary caps one user or role, an SCP caps all principals in a member account, and an RCP caps access to resources in a member account. None of them grants anything.
- Evaluation is an intersection with one early exit. An explicit deny anywhere wins, then RCPs, SCPs, identity policies, boundaries and session policies must all allow. A same-account resource-based policy can grant access past an implicit deny in a boundary, but never past an SCP or RCP.
- Use SCPs for people and accounts, boundaries for roles they create. AWS's own guidance is to restrict developers with SCPs and to require a boundary on the workload roles developers create.
- The management account is outside SCPs and RCPs. Neither affects principals or resources in the management account, and neither affects service-linked roles. Boundaries still apply there.
- A boundary is only as good as its enforcement. AWS does not attach a boundary automatically; the iam:PermissionsBoundary condition on create actions is what makes it mandatory.
The short answer
Use an SCP when the rule must hold for every principal in an account or OU, whoever created them: no unapproved Regions, no leaving the organisation, no disabling CloudTrail, no new IAM users. Use a permissions boundary when you let someone else create IAM roles or users and need to cap what those new identities can ever do. Use an RCP when the question is who may reach your resources, including principals outside your organisation. Most mature estates use all three: SCPs and RCPs set the organisation-wide perimeter, and boundaries contain delegated role creation inside each account. The AWS Security Blog puts it directly: SCPs are the better tool for restricting developers, because one SCP restricts every principal in the account, while boundaries belong on the roles developers create.
Side-by-side comparison
| Property | Permissions boundary | Service control policy | Resource control policy |
|---|---|---|---|
| Attached to | One IAM user or role (one boundary per entity) | Organisation root, OU or member account | Organisation root, OU or member account |
| Caps | Identity-based permissions of that entity | Permissions of principals in the account, including the member root user | Permissions on resources in the account, for any principal |
| External principals | Not applicable (it caps your own entity) | Not affected | Affected |
| Management account | Applies | Not affected | Not affected |
| Who sets it | Whoever creates or edits the entity, controlled by iam:PermissionsBoundary conditions | Organisation administrators in the management or delegated account | Organisation administrators |
| Service coverage | All IAM-authorised actions | All IAM-integrated services, with a short list of exceptions | A defined list of services, including S3, STS, KMS, SQS, Secrets Manager and others |
| Size | 6,144 characters (managed policy) | See AWS Organizations quotas | See AWS Organizations quotas |
| Bypassed by same-account resource policy grants | Yes, for grants to an IAM user ARN or a role session ARN | No | No |
| Typical owner | Platform or IAM team, consumed by product teams | Cloud security or platform team | Cloud security team (data perimeter) |
How they combine: the evaluation logic
For a request inside a single account, AWS documents this order. Every step either ends the evaluation or passes to the next:
- Explicit deny anywhere. AWS checks SCPs, RCPs, resource-based policies, identity-based policies, boundaries and session policies. One applicable Deny ends evaluation with Deny.
- RCPs. No applicable Allow in the RCPs means Deny. RCPFullAWSAccess is attached automatically when RCPs are enabled and cannot be detached, so this step only bites through Deny statements in practice.
- SCPs. No applicable Allow in the SCPs at every level means Deny.
- Resource-based policies. An Allow here can end evaluation with Allow, even with an implicit deny in an identity policy, boundary or session policy, depending on the principal type in the grant. IAM role trust policies and KMS key policies are exceptions that must explicitly allow principals.
- Identity-based policies. No Allow means implicit Deny.
- Permissions boundary. If the boundary does not allow the action, implicit Deny.
- Session policy. For role and federated sessions with a session policy, the action must also be allowed there.
Two consequences matter for design. First, SCPs and RCPs sit before the resource-policy exit, so nothing in an account can grant past them. Second, a boundary sits after it, so a same-account resource policy that names an IAM user ARN or a role session ARN directly is not limited by the boundary's implicit deny. A grant to a role ARN is limited. AWS also notes that a wildcard principal with an aws:PrincipalArn condition is not limited by boundaries or session policies unless an identity policy contains an explicit deny. That is why the boundaries guide recommends explicit Deny statements in the boundary for the most sensitive actions.
For cross-account requests, AWS evaluates both sides: the requester's identity policy (and anything that limits it, including the boundary) in the requesting account, and the resource policy in the owning account. Both must allow. SCPs apply to principals managed by the requesting account; RCPs apply to resources in the owning account, regardless of which organisation the principal belongs to.
Worked evaluation outcomes
| Request | SCP | RCP | Identity policy | Boundary | Outcome |
|---|---|---|---|---|---|
| Bounded role calls iam:CreateUser | Allows | Not in scope | Allows iam:* | Excludes IAM | Deny (boundary implicit deny) |
| Bounded role runs ec2:RunInstances in an unapproved Region | Denies the Region | Not in scope | Allows | Allows | Deny (SCP explicit deny) |
| Unbounded admin role reads a bucket in a member account | Allows | Allows (same organisation) | Allows | None | Allow |
| Principal in another organisation reads the same bucket under a permissive bucket policy | Not in scope (external) | Denies outside aws:PrincipalOrgID | Its own account allows | Not your entity | Deny (RCP explicit deny) |
| Bounded role session named directly in a same-account Secrets Manager resource policy | Allows | Allows | No Allow | Excludes secretsmanager | Allow (resource policy grant to the session ARN is not limited by the boundary) |
| Same request, boundary includes explicit Deny on that secret | Allows | Allows | No Allow | Explicit Deny | Deny (explicit deny wins) |
| Admin role in the management account disables a trail | Not applied (management account) | Not applied | Allows | None | Allow |
Threat model for each guardrail
Permissions boundary
- Protects against: a principal with delegated IAM rights creating a role more powerful than itself and assuming it (ATT&CK T1098.003 Additional Cloud Roles). This is exactly what happened in the 230 million AWS environments campaign, where a leaked IAM user key that could create roles was used to create a role with AdministratorAccess and deploy Lambda functions across Regions.
- Does not protect against: a principal that can create roles without the iam:PermissionsBoundary condition, remove the boundary, or edit the boundary policy; same-account resource policy grants to user or session ARNs; anything in another account.
- Who it helps: product teams and CI/CD deployment roles that need to create workload roles without waiting on a central team.
Service control policy
- Protects against: any principal in a member account, including the member root user and an attacker using a stolen admin credential, doing something the organisation has prohibited: disabling logging, using unapproved Regions (T1535), leaving the organisation (T1666), creating IAM users and long-lived keys.
- Does not protect against: anything in the management account, service-linked roles, principals from other organisations using resource policies you wrote, and a small list of root-only tasks AWS documents as outside SCP control. It also does nothing fine-grained: SCPs are coarse by design.
- Who it helps: the cloud security team that needs a rule nobody in a member account can lift, including account administrators.
Resource control policy
- Protects against: principals outside your organisation reaching data through a misconfigured bucket, key or secret policy (T1530 Data from Cloud Storage), and enforcing baselines such as HTTPS-only on supported services.
- Does not protect against: actions on services outside the supported list, the management account, service-linked roles, and AWS managed KMS keys.
- Who it helps: data owners who cannot review every resource policy in every account. See the AWS Resource Control Policies and Data Perimeter Guide.
The delegated administration use case
Delegated administration is where the two are most often confused. The goal is to let a product team or pipeline create IAM roles for its workloads without giving it a path to administrator. The pattern needs both guardrails:
- Boundary on created roles: the delegated policy allows iam:CreateRole and related actions only when iam:PermissionsBoundary equals an approved boundary ARN. AWS's IAM User Guide example names this statement CreateOrChangeOnlyWithBoundary, with NoBoundaryPolicyEdit to stop edits to the boundary policy. Without the condition, the boundary is optional and therefore absent when it matters: AWS documents that a create action without the required boundary fails only because the condition demands it.
- SCP on the account: deny changes to platform and break-glass roles except by the platform pipeline, deny iam:CreateUser and iam:CreateAccessKey outside an exception OU, and deny deletion of boundaries outside the platform role. This catches a delegated policy that was mis-scoped in one account, which a boundary cannot do because it only constrains the entity it is attached to.
- Not a boundary on developers: AWS's blog warns against putting boundaries on developers themselves: an entity can have only one boundary, of limited size, and per-principal controls are less efficient than an SCP for account-wide restrictions.
The statement-by-statement delegated policy and the escalation paths it must close are in the AWS IAM Permissions Boundaries Guide. To test for paths you missed, see How to Find IAM Privilege Escalation Paths in AWS.
Decision table by scenario
| Scenario | Primary guardrail | Supporting guardrail | Why |
|---|---|---|---|
| Developers create Lambda execution roles in their own account | Boundary on created roles | SCP protecting platform roles and boundary deletion | The cap must follow each new role; the SCP stops the delegated policy being abused |
| No one may use Regions outside the EU | SCP with aws:RequestedRegion | None | Applies to every principal, whoever created it |
| Stop accounts leaving the organisation | SCP denying organizations:LeaveOrganization | None | Only an organisation policy can hold this |
| Only principals in our organisation may read our S3 data | RCP identity perimeter | SCP with aws:ResourceOrgID for the reverse direction | Bucket policies are written per resource; the RCP caps them all |
| A third-party CI service deploys into one account | Boundary on the deployment role and the roles it creates | RCP allowing the vendor's account explicitly; SCP on Regions | The vendor's role is your entity, so you can bound it |
| Protect CloudTrail and GuardDuty from tampering | SCP deny with platform-role exception | Boundary excluding those services from workload roles | Defence in depth: the SCP also covers account admins |
| Restrict the member account root user | Centralised root access plus SCP | None | Boundaries cannot be attached to the root user |
| Contain roles in the management account | Boundary and tight identity policies | Keep workloads out of it entirely | SCPs and RCPs do not apply there |
| Temporary task with narrower rights than a role | Session policy at AssumeRole | None | The caller chooses it, so it is a convenience, not a control over the caller |
Failure modes
- Boundary not attached on role creation. The delegated policy allows iam:CreateRole without the iam:PermissionsBoundary condition, or applies the condition to CreateRole but not to PutRolePermissionsBoundary. The first role without a boundary is the escalation path.
- Boundary policy editable. A delegated principal can create a new default version of the boundary policy, which silently widens every bounded role at once.
- Management account treated as covered. Workloads, CI pipelines or day-to-day admin users in the management account sit outside every SCP and RCP. AWS's guidance is to keep it clear of workloads and delegate administration of security services to member accounts, which SCPs do constrain.
- SCP exemption by broad wildcard. An exemption written as ArnNotLike on a whole account or a wildcard role path turns the guardrail into a suggestion for anyone who can create a role with a matching name.
- Relying on a boundary against resource-policy grants. A bucket, key or secret policy that names a role session or IAM user ARN directly grants past the boundary's implicit deny.
- Assuming an RCP covers every service. RCPs apply only to listed services; check the current list before relying on one for a new data store.
Worked scenario: platform team opening self-service IAM
A company with 180 member accounts wants product teams to create their own workload roles through Terraform. The cloud security team designs three layers:
- Organisation: root-level SCPs deny leaving the organisation and stopping CloudTrail; an OU-level SCP denies iam:CreateUser, iam:CreateAccessKey and iam:DeleteRolePermissionsBoundary except for the platform pipeline role; an RCP identity perimeter covers S3, KMS and Secrets Manager.
- Account: each team's deployment role carries the delegated administrator policy, which allows role creation only with one of three boundary ARNs (analytics, web services, data processing) and only under the role/applicationroles/ path, with iam:PassRole limited to that path.
- Role: every created workload role carries a boundary that excludes IAM, Organizations and STS AssumeRole into arbitrary roles, with explicit denies on the security team's secrets.
In testing, a deliberately mis-scoped delegated policy in one account let a test principal create a role without a boundary. The SCP did not stop the creation, but it did stop the new role from deleting boundaries or touching platform roles, and the CloudTrail alert for CreateRole without an approved boundary fired. The team fixed the policy before rollout. Neither layer alone would have contained the test.
How to implement: phased approach
- Map the current state. List who can create IAM roles and users in each account, which accounts run workloads in the management account, and which SCPs and RCPs are attached at each level.
- Clear the management account. Move workloads and pipelines out; delegate administration of security services to member accounts.
- Deploy organisation guardrails first. Deny-list SCPs and an RCP identity perimeter, tested in a Policy Staging OU, promoted from sandbox to production OUs, then the root.
- Introduce boundaries with delegation. Write the boundary and delegated policies as code; validate with IAM Access Analyzer; run negative tests (create without boundary, delete boundary, edit boundary policy, pass a platform role) and confirm each is denied.
- Backfill. Attach boundaries to existing roles in delegated paths after checking last-accessed data.
- Roll back safely. SCPs and RCPs are rolled back by detaching from the OU or moving the account; delegation is rolled back by detaching the delegated policy. Boundaries already on roles can stay, since they only restrict.
Detection and measurement
Send CloudTrail from every account, including the management account, to a log archive account. Alert on CreateRole or CreateUser without an approved permissionsBoundary, on DeleteRolePermissionsBoundary, on CreatePolicyVersion or SetDefaultPolicyVersion against a boundary policy ARN, on Organizations events such as DetachPolicy, UpdatePolicy and MoveAccount, and on AccessDenied spikes from SCP or RCP explicit denies. The AWS AccessDenied Troubleshooting Guide explains how the error context identifies which policy type denied.
- Boundary coverage: share of roles in delegated paths that carry an approved boundary, target 100%.
- Unbounded creation events: count of CreateRole events in delegated accounts without an approved boundary, target zero.
- Management account workload count: number of non-administrative roles or workloads in the management account, target zero.
- SCP exemption count: number of principal ARN patterns exempted from root and OU SCPs, trending down.
- Guardrail drift: days with a difference between attached policies and the source repository, target zero.
Common failure patterns
- Using boundaries to restrict developers. One boundary per entity and limited size make this brittle; restrict developers with an SCP.
- Using an SCP for per-workload least privilege. SCPs are account-wide and coarse; fine-grained limits belong in identity policies and boundaries.
- Untested SCP at the root. AWS strongly recommends not attaching untested policies to the organisation root; a missing Allow at one level denies everything below it.
- Long-lived IAM user keys with role-creation rights. As the 230 million environments campaign showed, a leaked key with iam:CreateRole and iam:AttachRolePolicy is an administrator key unless a boundary condition or SCP stops it. See the AWS IAM Roles vs IAM Users guide.
- Forgetting service-linked roles. Neither SCPs nor RCPs restrict them; review which services have them in sensitive accounts.
Framework mapping
| Framework | Reference | How it applies |
|---|---|---|
| NIST CSF 2.0 | PR.AA-05, PR.PS-01 | Least-privilege permissions enforced by policy; guardrails managed as configuration |
| NIST SP 800-53 Rev 5 | AC-3, AC-6, AC-6(9), AC-6(10), CM-5 | Access enforcement, least privilege, logging privileged functions, preventing non-privileged users executing privileged functions, restricting who can change guardrails |
| CIS Controls v8.1 | 6.8 | Define and maintain role-based access control |
| ISO/IEC 27001:2022 Annex A | A.5.15, A.8.2 | Access control and privileged access rights |
| MITRE ATT&CK | T1098.003, T1078.004, T1535, T1530, T1666 | Additional cloud roles, cloud accounts, unused Regions, data from cloud storage, modifying cloud resource hierarchy |
Practitioner checklist
- Decide per rule whether it must hold for every principal (SCP), every resource (RCP) or every delegated role (boundary).
- Keep the management account free of workloads; treat it as outside every SCP and RCP.
- Require iam:PermissionsBoundary on every create and put-boundary action in delegated policies.
- Deny deletion of boundaries and edits to boundary policies, in the delegated policy and again by SCP.
- Add explicit denies in boundaries for sensitive actions that resource policies could otherwise grant.
- Apply the RCP identity perimeter to supported data services and check the supported list for new ones.
- Test every guardrail in a staging OU or sandbox account with negative tests before promotion.
- Alert on unbounded role creation, boundary deletion and Organizations policy changes.
Standards and references
- AWS: Policy evaluation logic within a single account
- AWS: Cross-account policy evaluation logic
- AWS: Permissions boundaries for IAM entities
- AWS: Service control policies
- AWS: Resource control policies
- AWS Security Blog: When and where to use IAM permissions boundaries
Related NHI Mgmt Group resources: AWS IAM Permissions Boundaries Guide · AWS Organizations and SCPs Guide · AWS Resource Control Policies and Data Perimeter Guide · Cloud PAM and CIEM Guide