Skip to main content
cd ../config-traps
risk/register/root-exemptions-in-scps-undo-every-deny-clause.html
AWS Organizations Guardrailscritical severityAWS Organizations

Root Exemptions in SCPs Undo Every Deny Clause

Severity
critical
Reviewed
23 Jul 2026
Remediation
~20 minutes
Overview

Across many AWS Organizations, custom Deny SCPs inherit a PrincipalArn exemption originally written to stop root lockout, so root sessions in member accounts skip every guardrail built afterwards. When root credentials are exposed, no SCP statement blocks LeaveOrganization or StopLogging, and the same session can erase the evidence.

Operational summary

At a glance

Symptom
Root credentials in a member account are used, via password reset or a leaked access key, to call high-risk APIs that every Deny SCP…
Likely cause
Deny SCP statements carry a blanket aws:PrincipalArn exemption for the account's root user, copied from lockout-prevention guidance into unrelated guardrails.
Impact
Root can leave the Organization, disable CloudTrail and GuardDuty, and expose data with no SCP guardrail intervening at any point.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Scope the root exemption to AWS's documented root-only tasks and enforce unconditional Deny statements on high-risk actions, or adopt centralised root access management.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

The Blanket Root Exemption Clause. AWS’s own guidance warns against writing an unconditional Deny SCP against iam:* because it can permanently lock an account out of root-only tasks. To satisfy that guidance, teams add a Condition block to their Deny statements matching aws:PrincipalArn against arn:aws:iam::*:root with StringNotEquals, exempting root from the Deny entirely. That exemption block then gets copied wholesale into every subsequent SCP the security team writes, regardless of what the statement is actually protecting.

The Default State

Landing zone baselines and hand-rolled guardrail libraries typically ship one root-exemption SCP for account-recovery reasons, then reuse its Condition syntax as boilerplate. A Deny statement targeting cloudtrail:StopLogging, guardduty:DeleteDetector, or organizations:LeaveOrganization gets the same StringNotEquals root exemption pasted in, on the assumption that “root always needs an escape hatch.” No one revisits which actions genuinely require that exemption versus which ones are simply carrying it forward unreviewed. The SCP evaluates correctly for IAM users and roles; it does nothing for root.

The Blast Radius

Root in a member account has no attached IAM policy to constrain it and, if MFA was never enforced on that credential, a password reset or a leaked long-term access key is enough. Once authenticated as root, the attacker calls organizations:LeaveOrganization to detach the account from the Organization outright, removing every remaining SCP in one step, or simply stays inside and calls cloudtrail:StopLogging and guardduty:DeleteDetector first. Every one of those actions was covered by a Deny SCP that exempted root by principal. Forensics collapse because the same session that exfiltrated data also disabled the logging that would have proven it.

The Lead Mechanic Fix

Stop treating the root exemption as reusable boilerplate. Restrict it to the literal set of tasks AWS documents as requiring root — closing the account, changing account settings, viewing tax invoices, restoring a locked-out IAM user, changing the support plan — and write those as one narrowly scoped SCP statement with an explicit ForAllValues:StringEquals action list, not a blanket NotAction. Every other Deny statement — organizations:LeaveOrganization, cloudtrail:StopLogging, cloudtrail:DeleteTrail, guardduty:DeleteDetector, iam:CreateAccessKey against root itself — must carry zero principal exemption. Better still, enable IAM’s centralised root access management from the management account, which deletes long-term root credentials in member accounts and routes emergency root actions through the management account, removing the need for a blanket exemption in the first place.

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

ForAllValues:StringEquals
NotAction
organizations:LeaveOrganization
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

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