gcp-orgpolicy-modify-drs-guardrail
Weaken iam.allowedPolicyMemberDomains to allow granting roles to external identities.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?orgpolicy) ==
OrganizationPolicy
?orgpolicy.constraint == 'constraints/iam.allowedPolicyMemberDomains'
?orgpolicy is ENFORCED at/inherited-to ?scope (list constraint restricting allowed domains)
?principal has EFFECTIVE orgpolicy.policy.set at ?scope
emit
| source type | Identity |
|---|---|
| target type | * |
| source | ?principal |
| target | ?orgpolicy |
| permissions | orgpolicy.policy.set |
| conditions | guardrail_enforced iam_permission |
| state logic | ACTIVE for the CanModifyPolicy when set is unconditional and the list constraint is enforced at ?scope. The unblocked cross-org grant edge is upgraded by hierarchy-chains; it additionally requires the principal to hold a setIamPolicy grant capability to actually add the external member (that capability is the identity-escalation.yaml edge, not this one). |
Narrative
{principal.name} can weaken constraints/iam.allowedPolicyMemberDomains at {scope.name}, allowing external attacker-owned identities to be granted IAM roles in {scope.name} (cross-org grant).
Raw rule rules/derived/gcp/orgpolicy.yaml
id: gcp-orgpolicy-modify-drs-guardrail
emits: CanModifyPolicy
description: Weaken iam.allowedPolicyMemberDomains to allow granting roles to external identities.
match:
- - principal: null
- CanModifyPolicy
- orgpolicy: null
where:
- node_type(?orgpolicy) == OrganizationPolicy
- ?orgpolicy.constraint == 'constraints/iam.allowedPolicyMemberDomains'
- ?orgpolicy is ENFORCED at/inherited-to ?scope (list constraint restricting allowed domains)
- ?principal has EFFECTIVE orgpolicy.policy.set at ?scope
emit:
source_type: Identity
target_type: '*'
source: ?principal
target: ?orgpolicy
permissions:
- orgpolicy.policy.set
gates:
- 'external-member grant / CrossProjectTrust / CanFederateAs # add an attacker-owned external principal
via setIamPolicy'
conditions:
- guardrail_enforced
- iam_permission
state_logic: ACTIVE for the CanModifyPolicy when set is unconditional and the list constraint is enforced
at ?scope. The unblocked cross-org grant edge is upgraded by hierarchy-chains; it additionally requires
the principal to hold a setIamPolicy grant capability to actually add the external member (that capability
is the identity-escalation.yaml edge, not this one).
confidence: min(contributing_confidences)
derived_from:
- ?principal CanModifyPolicy ?orgpolicy
- guardrail-removal-upgrades-blocked (hierarchy-chains.yaml)
false_positive_note: "Domain Restricted Sharing only blocks ADDING out-of-domain members; it does not\
\ itself grant anything. This rule is meaningful only when a cross-org/external-member grant edge\
\ exists as BLOCKED by THIS policy AND the principal (or a reachable identity) can also perform the\
\ setIamPolicy that would add the external member. Widening the allowed-domains list to include an\
\ attacker domain is equivalent to removal \u2014 treat allowValues edits that add attacker-controllable\
\ domains as weakening."
narrative: '{principal.name} can weaken constraints/iam.allowedPolicyMemberDomains at {scope.name},
allowing external attacker-owned identities to be granted IAM roles in {scope.name} (cross-org grant).'