aws-account-root-recovery-ownership
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?root) ==
HumanIdentity and ?root is the root user of an Account
emit
| source type | Identity |
|---|---|
| target type | * |
| source | <principal> |
| target | <Account of ?root> |
| permissions | account:PutContactInformation account:PutAlternateContact account:StartPrimaryEmailUpdate |
| conditions | scp_or_org_policy condition_expression |
| state logic | Inherit from the contributing CanResetCredential: CONDITIONAL(reset-flow) while the reset is unrealized, BLOCKED if an SCP denies the underlying account:Put* actions. Root sits ABOVE all IAM policy, so owning root == controlling the whole account; the only guardrail is an SCP restricting root or the account:Put* actions. |
Narrative
{principal.name} can take over the root user of {target.name} and thereby own the account outright, beyond the reach of any IAM policy.
Raw rule rules/explicit/aws-account.yaml
id: aws-account-root-recovery-ownership
emits: CanTakeOwnership
applies_to:
- aws
match:
- - principal: null
- CanResetCredential
- root: null
where:
- node_type(?root) == HumanIdentity and ?root is the root user of an Account
emit:
source_type: Identity
target_type: '*'
source: <principal>
target: <Account of ?root>
api_source: "derived from CanResetCredential(root) \u2014 see aws-account-root-credential-reset"
permissions:
- account:PutContactInformation
- account:PutAlternateContact
- account:StartPrimaryEmailUpdate
conditions:
- scp_or_org_policy
- condition_expression
state_logic: 'Inherit from the contributing CanResetCredential: CONDITIONAL(reset-flow) while the reset
is unrealized, BLOCKED if an SCP denies the underlying account:Put* actions. Root sits ABOVE all IAM
policy, so owning root == controlling the whole account; the only guardrail is an SCP restricting
root or the account:Put* actions.'
false_positive_note: Only as strong as the root reset itself (CONDITIONAL(reset-flow)); do not promote
to ACTIVE just because the write permission exists. If the account is a member with an SCP restricting
root actions the ownership is partial -> keep the SCP gate. Feeds can-control's control-via-admin
roll-up (CanTakeOwnership over an AdministrativeBoundary => Controls(Account)).
narrative: '{principal.name} can take over the root user of {target.name} and thereby own the account
outright, beyond the reach of any IAM policy.'