Skip to content

GWS_ADD_GROUP_MEMBER

Copy page

Summary

Forestall ACL Alias GWS_ADD_GROUP_MEMBER
GWS Alias Add Group Member
Affected Object Types GWS Group
Exploitation Certainty Certain
Granting Roles / Positions Google Workspace Super Admin, Groups Admin (directory role), existing Group Owner, existing Group Manager

Description

GWS_ADD_GROUP_MEMBER represents the ability to add new members to a Google Workspace Group. When a controlled identity is added as a member of a group, it immediately inherits all GCP IAM roles bound to that group at any resource scope (organization, folder, project, or resource level).

Group membership changes are recorded exclusively in Google Workspace audit logs (admin.googleapis.com or groups_enterprise application). The GCP IAM audit log event setIamPolicy is never triggered by group membership changes, so defenders monitoring only GCP Cloud Audit Logs will not detect this escalation. Additionally, member additions via the Groups UI route to the groups_enterprise stream while Admin API additions route to the admin stream — monitoring only one stream misses the other.

When an identity is added, it immediately gains access to the group’s entire email conversation history and archive. This historical access generates no audit event.

Groups created via the GCP IAM console (not the Google Admin Console) inherit the organization-wide default that allows any org member to self-join via the Groups UI without any admin action. This behavior was classified by Google as “Won’t Fix (Intended Behavior)” (NetSPI VRP disclosure, July 2024). If a group has allowExternalMembers=true, external identities can also be added, bypassing Domain-Restricted Sharing policies.

Identification

gcloud CLI

# Find all GCP-bound groups across the organization
gcloud asset search-all-iam-policies \
--scope='organizations/ORG_ID' \
--query='memberTypes:group' \
--format="table(resource, policy.bindings[].role, policy.bindings[].members)"
# Identify who currently has OWNER or MANAGER roles on a group (can add members)
GROUP_EMAIL="[email protected]"
gcloud identity groups memberships list \
--group-email=$GROUP_EMAIL \
--format="table(preferredMemberKey.id, roles[0].name)" \
| grep -E "OWNER|MANAGER"
# Find open-join groups (any org member can self-join without admin action)
# Check join policy for each GCP-bound group via the Groups Settings API
PROJECT_ID="my-project"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
jq -r '.bindings[] | .members[] | select(startswith("group:"))' | sort -u

Exploitation

# Add attacker-controlled identity as MEMBER via Directory API
GROUP_EMAIL="[email protected]"
curl -X POST \
"https://admin.googleapis.com/admin/directory/v1/groups/$GROUP_EMAIL/members" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "role": "MEMBER"}'
# Wait 1-5 minutes for GCP IAM propagation, then verify inherited access
gcloud projects list
gcloud storage ls

Mitigation

  1. Convert GCP-bound groups to security groups — security groups restrict membership modification to Super Admins only, eliminating open-join policies:
    gcloud identity groups update GROUP_EMAIL \
    --labels=cloudidentity.googleapis.com/groups.security=''
  2. Audit and remediate open group join policies — groups created via GCP IAM console may inherit permissive join policies. Set to Only invited users via Google Admin Console → Directory → Groups → group → Group settings → Who can join.
  3. Disable external membership for sensitive groups via Google Admin Console → group settings → disable Allow members outside your organization.
  4. Minimize owners and managers on GCP-bound groups to reduce the number of principals who can exercise this permission.
  5. Enable GWS audit log export to Cloud Logging — without this, groups_enterprise events (including self-join events) are invisible to GCP-based monitoring.
  6. Audit GCP IAM group bindings regularly:
    gcloud asset search-all-iam-policies \
    --scope='organizations/ORG_ID' \
    --query='memberTypes:group'

Detection

Group membership additions appear only in Google Workspace Audit Logs, not in GCP IAM audit logs. Monitor both the admin and groups_enterprise streams — each captures a different addition method.

Google Admin Console

  1. Open Google Admin Console (admin.google.com) → Reporting → Audit and investigation → Groups Enterprise log events.
  2. Filter by Event Name: Add member (API-based) or Event Name: join (self-join via Groups UI).
  3. Cross-reference the Target group against groups with GCP IAM bindings.

Cloud Logging (GCP)

# Monitor API-based group member additions
gcloud logging read \
'logName="organizations/ORG_ID/logs/cloudaudit.googleapis.com%2Factivity" AND protoPayload.serviceName="admin.googleapis.com" AND protoPayload.methodName="google.admin.AdminService.addGroupMember"' \
--format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.request.groupKey, protoPayload.request.memberKey)"

References

Was this page helpful?

Thank you for your feedback.