gcp-ci-group-member-inherits-role

Principal with cloudidentity.groups.memberships.create (or group Manager/Owner role) can add any principal - including itself - to the target group, inheriting its bound GCP IAM roles.

derived gcp emits CanAddMember

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} HasPermission {'group': None}

where

node_type(?group) == Group effective_permission(?principal, cloudidentity.groups.memberships.create, ?group) == true OR membership_role(?principal, ?group) in [MANAGER, OWNER]

emit

source typeIdentity
target typeGroup
source?principal
target?group
permissionscloudidentity.groups.memberships.create
conditionsiam_permission
state logicACTIVE if effective permission is confirmed at the group scope (role binding that grants cloudidentity.groups.memberships.create, or the principal is a group MANAGER/OWNER). CONDITIONAL(iam_permission) if permission is inherited from a parent resource and not yet confirmed. BLOCKED if an IAM deny policy explicitly denies cloudidentity.groups.memberships.create on the group. Note: even ACTIVE, a downstream CanGrantPermission edge is only meaningful if the group actually has a GCP IAM role binding — without one, this is group-membership access only (still a finding but lower-impact).

Narrative

{principal.name} can add any principal (including itself) to {group.name} (cloudidentity.groups.memberships.create or group Manager/Owner role). Any GCP IAM role bound to {group.name} is inherited by the added principal, making this a privilege-escalation vector when {group.name} carries elevated IAM roles.

Raw rule rules/derived/gcp/cloudidentity.yaml

id: gcp-ci-group-member-inherits-role
emits: CanAddMember
description: "Principal with cloudidentity.groups.memberships.create (or group Manager/Owner role) can\
  \ add any principal \u2014 including itself \u2014 to the target group, inheriting its bound GCP IAM\
  \ roles."
match:
- - principal: null
  - HasPermission
  - group: null
where:
- node_type(?group) == Group
- effective_permission(?principal, cloudidentity.groups.memberships.create, ?group) == true OR membership_role(?principal,
  ?group) in [MANAGER, OWNER]
emit:
  source_type: Identity
  target_type: Group
  source: ?principal
  target: ?group
  permissions:
  - cloudidentity.groups.memberships.create
  conditions:
  - iam_permission
  state_logic: "ACTIVE if effective permission is confirmed at the group scope (role binding that grants\
    \ cloudidentity.groups.memberships.create, or the principal is a group MANAGER/OWNER). CONDITIONAL(iam_permission)\
    \ if permission is inherited from a parent resource and not yet confirmed. BLOCKED if an IAM deny\
    \ policy explicitly denies cloudidentity.groups.memberships.create on the group. Note: even ACTIVE,\
    \ a downstream CanGrantPermission edge is only meaningful if the group actually has a GCP IAM role\
    \ binding \u2014 without one, this is group-membership access only (still a finding but lower-impact)."
  confidence: 0.95
  derived_from:
  - effective cloudidentity.groups.memberships.create on ?group (or MANAGER/OWNER membership role)
  false_positive_note: "A group MEMBER cannot add members \u2014 only a MANAGER/OWNER or a principal with\
    \ the explicit cloudidentity.groups.memberships.create permission at the group scope can do so. Check\
    \ both the IAM binding AND the membership role. Also verify the group has at least one GCP IAM role\
    \ binding (HasRole) to confirm this is a privilege-escalation vector and not just group management.\
    \ Admin SDK admin.directory.groups.members.insert is the Workspace-equivalent path \u2014 if the collector\
    \ uses Admin SDK, map that permission to this rule. An org-level roles/cloudidentity.groupAdmin covers\
    \ all groups; a group-scoped binding is narrower \u2014 honor the scope."
  narrative: '{principal.name} can add any principal (including itself) to {group.name} (cloudidentity.groups.memberships.create
    or group Manager/Owner role). Any GCP IAM role bound to {group.name} is inherited by the added principal,
    making this a privilege-escalation vector when {group.name} carries elevated IAM roles.'
move · open · esc close