Cloud Security · 8 min · Apr 21, 2026
Cloud SecurityThe Deny Is the Perimeter
SCPs set the ceiling that still holds when an IAM policy is wrong. Paired with resource control policies, they're how you draw a real boundary around your data.
Most teams review IAM policies closely and treat the org-level deny as a footnote. That's backwards. An explicit deny in a service control policy overrides any allow in a member account, including that account's root user. When someone attaches AdministratorAccess for a weekend migration and forgets to take it off, the SCP is what still holds.
That insight is real. The mistake is stopping there. SCPs are the outer bound for identities inside your organization, not usually the bound that decides a breach. Effective permissions are the overlap of SCPs, IAM policies, permission boundaries, and session policies. Most SCPs are broad guardrails — deny unused regions, deny disabling CloudTrail — so for a compromised role, its IAM policy is still what decides the blast radius.
And SCPs alone aren't a perimeter around your data. They don't stop a bucket or key policy from granting access to an account outside the organization. AWS's data-perimeter model pairs them with resource control policies, which cap what those resource policies can grant, and with VPC endpoint policies on the network path.
What it looks like in practice
A platform team spends a week tightening the IAM policy on a deployment role. The review is careful. Nobody opens the SCPs, because those were written two years ago and "just deny the obvious things."
Friday afternoon, a migration stalls. Someone attaches AdministratorAccess to the same role "for the weekend." The SCP still does its job: the role can't stop CloudTrail, can't leave the organization, and can't call APIs in regions you don't use. On Monday the extra policy is still there. The role can now read every S3 bucket in the account. Nothing in the SCP said otherwise, because nobody writes an SCP that enumerates every sensitive action.
Separately, a bucket policy from the same migration trusts an account that isn't in the organization. The SCP never sees that grant. Identity policies constrain principals you own. Resource policies can invite principals you don't.
The ceiling, not the room
An SCP never grants access. It sets the maximum an IAM principal in a member account is allowed to have. The actual permission is the intersection: the SCP allow-list, the identity policy, any permission boundary, any session policy, and — if the call is to a resource with its own policy — that resource policy too.
That's why "the deny is the perimeter" is true in one direction and false in the other. The deny is the ceiling. It still holds when an IAM policy is wrong. It is not a substitute for the IAM policy. If your SCPs only block unused regions and a handful of break-the-glass APIs, a role with AdministratorAccess still has the run of the account.
Write SCPs for things you never want anyone in a member account to do. Leave the day-to-day blast radius to IAM, and review both.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyLeaveOrganization",
"Effect": "Deny",
"Action": "organizations:LeaveOrganization",
"Resource": "*"
},
{
"Sid": "ProtectSecurityTooling",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail",
"cloudtrail:UpdateTrail",
"cloudtrail:PutEventSelectors",
"config:StopConfigurationRecorder",
"config:DeleteConfigurationRecorder",
"config:DeleteDeliveryChannel",
"guardduty:DeleteDetector",
"guardduty:UpdateDetector",
"guardduty:DisassociateFromAdministratorAccount",
"securityhub:DisableSecurityHub"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdmin"
}
}
}
]
}Where SCPs stop
Two gaps belong in every write-up of "the real bound," because they surprise people who treated the SCP as a perimeter:
- SCPs do not apply to the management account. Identities there, including that account's root, are outside the ceiling. That's one reason AWS tells you not to run workloads in it.
- SCPs do not apply to service-linked roles. Those roles exist so AWS services can do their job in your account, and the SCP can't clip them.
The third gap is the one that turns an SCP into a false perimeter: resource-based policies. A bucket policy, a KMS key policy, or an SQS queue policy can grant an outside account access even when every identity in your organization is tightly scoped. The SCP never evaluates that grant. It only evaluates principals in member accounts.
Pair the deny with a resource control policy
Resource control policies are the other half of the identity bound. An SCP caps what principals inside the organization can do. An RCP caps what a resource in a member account can be talked into granting, including to principals outside the organization. No RCP grants access; like an SCP, it only sets a ceiling.
AWS's data-perimeter guidance treats three controls as a set: SCPs for your identities, RCPs for your resources, and VPC endpoint policies for the network path. Skip any one, and the other two have a hole.
An RCP that keeps S3 and KMS inside the organization looks like this. o-xxxxxxxxxx is a placeholder for your organization ID. The aws:PrincipalIsAWSService exception is there so AWS services can still do their job; test it against backup, logging, and deployment paths before you attach it widely.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "KeepDataInsideTheOrganization",
"Effect": "Deny",
"Principal": "*",
"Action": ["s3:*", "kms:*"],
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:PrincipalOrgID": "o-xxxxxxxxxx"
},
"BoolIfExists": {
"aws:PrincipalIsAWSService": "false"
}
}
}
]
}RCPs have the same honesty requirements as SCPs. They don't apply to the management account. They don't apply to service-linked roles. They don't apply to AWS managed KMS keys. And they only cover a specific list of services — S3, KMS, Secrets Manager, SQS, STS, ECR, and a growing set of others — not every resource in the account. An RCP is not a blanket "no external access" switch.
If you've already seen the deny-cross-account KMS decrypt SCP on the Data Security topic page, treat it as the identity-side half of this pair. That SCP stops roles in other accounts inside your organization from using a prod-tagged key. It does not stop the key policy itself from trusting an account outside the organization. The RCP is what closes that window.
What to do
- Review SCPs with the same care as IAM policies. They're the ceiling that still holds when an identity policy is wrong.
- Write SCPs as guardrails for things you never want a member account to do: leave the org, disable logging, use regions you don't operate in. Don't try to encode every least-privilege decision in them.
- Keep treating IAM as the control that decides blast radius for a compromised role. Permission boundaries and session policies sit in that same intersection.
- Add RCPs for the data stores that shouldn't be shareable outside the organization, starting with S3 and KMS.
- Don't run workloads in the management account. SCPs and RCPs don't apply there.
- Account for service-linked roles. Neither policy type constrains them.
- Attach new SCPs and RCPs to a test account, then an OU, then wider. Watch CloudTrail for unexpected AccessDenied before you call it done.
- Include VPC endpoint policies if your data path is supposed to stay on a private network. The identity bound isn't the network bound.
The takeaway
The deny is the ceiling. IAM is still the room. A resource control policy is what closes the window an SCP can't see.
Draw the bound with all three, or don't call it a perimeter.