AWS SCPs Don't Restrict Root Sessions by Default
A missing explicit deny on aws:PrincipalType Root lets root sessions in member accounts execute unrestricted API calls, and the management account root sits entirely outside SCP enforcement, so a single credential recovery leaves AWS Organizations with no working guardrail.
Operational summary
At a glance
- Symptom
- A member account root session, recovered or phished via the account email and phone flow, calls an unrestricted API such as organizations:LeaveOrganization or cloudtrail:StopLogging.
- Likely cause
- Root OU SCPs contain no Deny statement conditioned on aws:PrincipalType Root, and the management account has no root credential hardening.
- Impact
- Root can detach accounts from the organization, delete CloudTrail trails and disable GuardDuty before any IAM-scoped alerting has a chance to fire.
- Verification signal
- Re-run the detection test and a controlled negative-path test.
- Safe correction
- Attach an explicit Deny SCP scoped to aws:PrincipalType Root at the Root OU and enforce hardware MFA with no access keys on the management account root user.
- Rollback or recovery
- Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.
The Trap
Service Control Policies attached to the Organizations Root OU without an explicit Deny statement conditioned on aws:PrincipalType equalling Root. Teams assume the standard FullAWSAccess baseline SCP, layered with a handful of preventive Deny SCPs targeting services, automatically constrains root sessions the same way it constrains IAM users and roles. It does not, because AWS evaluates SCPs against the principal type, and Allow statements never restrict anything on their own.
The Default State
Landing zone deployments attach FullAWSAccess to the Root OU by default and layer service-scoped Deny SCPs beneath it, but almost none of those Deny statements include a Condition block matching aws:PrincipalType: “Root”. Separately, and structurally rather than as a misconfiguration, AWS never applies any SCP to the organization’s management account, regardless of where that SCP sits in the hierarchy. Engineers who verify SCP coverage against member accounts often extrapolate that coverage upward and stop hardening the management account root user, leaving it with no MFA device registered and, occasionally, live access keys.
The Blast Radius
Root is the only principal SCPs are specifically designed to constrain in member accounts, because IAM policies cannot touch root at all. Without a scoped Deny, a phished or account-recovery-hijacked root session in a member account can call organizations:LeaveOrganization to detach itself from central logging and SCP enforcement, run cloudtrail:StopLogging or cloudtrail:DeleteTrail to blind the security team, and call guardduty:DeleteDetector to remove detection entirely, all before any IAM-based alerting fires. In the management account, none of this even requires bypassing an SCP, because no SCP was ever in scope: a compromised management account root session has unconditional control over every linked account, every SCP, and every StackSet.
The Lead Mechanic Fix
Attach a Deny SCP at the Root OU with a Condition block: {“Effect”:”Deny”,”Action”:[“organizations:LeaveOrganization”,”cloudtrail:StopLogging”,”cloudtrail:DeleteTrail”,”guardduty:DeleteDetector”,”iam:DeleteAccountPasswordPolicy”],”Resource”:”*”,”Condition”:{“StringEquals”:{“aws:PrincipalType”:”Root”}}}. Enforce a hardware MFA device on the management account root user, delete any root access keys, and configure the centralised root access feature in IAM so member account root sign-in requires management account approval. Add an EventBridge rule matching CloudTrail’s userIdentity.type Root against RootAccountUsage to page on-call immediately, since this is the only account where an SCP cannot save you.
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.
Attach an explicit Deny SCP scoped to aws:PrincipalType Root at the Root OU and enforce hardware MFA with no access keys on the management account root user.
Validate the vendor-specific syntax in official documentation before applying it.
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.