gcp-pd-snapshot-public-tenant

A snapshot with allAuthenticatedUsers or allUsers in its IAM policy is exposed to all GCP identities (authenticated or nominally public) across all projects/organizations.

derived gcp emits ExposedToTenant

match

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

{'snapshot': None} HasPolicy {'policy': None}

where

node_type(?snapshot) == Snapshot ?policy contains a member in [allAuthenticatedUsers, allUsers] the member's role grants compute.snapshots.useReadOnly

emit

source typeSnapshot
target typeOrganization
source<snapshot>
target<GCP organization / all-authenticated-tenant>
permissionscompute.snapshots.useReadOnly
conditionsresource_policy
state logicACTIVE when the snapshot IAM policy contains an allAuthenticatedUsers or allUsers binding with a role that grants compute.snapshots.useReadOnly (e.g., roles/compute.storageAdmin, roles/owner, custom roles). Both members are emitted as ExposedToTenant because both require GCP authentication to consume the snapshot (compute.disks.create requires a valid credential). allAuthenticatedUsers explicitly requires GCP auth; allUsers is nominally public-facing but in practice also requires GCP auth for block storage snapshot restoration.

Narrative

{snapshot.name} has an IAM binding granting {principal} read access (compute.snapshots.useReadOnly), exposing the snapshot's contents to all GCP-authenticated identities (or all holders of GCP credentials for allUsers). Any GCP-authenticated identity across accounts/projects can create a disk from this snapshot and read its data.

Raw rule rules/derived/gcp/pd.yaml

id: gcp-pd-snapshot-public-tenant
emits: ExposedToTenant
description: A snapshot with allAuthenticatedUsers or allUsers in its IAM policy is exposed to all GCP
  identities (authenticated or nominally public) across all projects/organizations.
applies_to:
- gcp
match:
- - snapshot: null
  - HasPolicy
  - policy: null
where:
- node_type(?snapshot) == Snapshot
- ?policy contains a member in [allAuthenticatedUsers, allUsers]
- the member's role grants compute.snapshots.useReadOnly
emit:
  source_type: Snapshot
  target_type: Organization
  source: <snapshot>
  target: <GCP organization / all-authenticated-tenant>
  permissions:
  - compute.snapshots.useReadOnly
  conditions:
  - resource_policy
  state_logic: ACTIVE when the snapshot IAM policy contains an allAuthenticatedUsers or allUsers binding
    with a role that grants compute.snapshots.useReadOnly (e.g., roles/compute.storageAdmin, roles/owner,
    custom roles). Both members are emitted as ExposedToTenant because both require GCP authentication
    to consume the snapshot (compute.disks.create requires a valid credential). allAuthenticatedUsers
    explicitly requires GCP auth; allUsers is nominally public-facing but in practice also requires GCP
    auth for block storage snapshot restoration.
  false_positive_note: "Emit ExposedToTenant for both allAuthenticatedUsers and allUsers. While allUsers\
    \ nominally suggests internet exposure, block storage access always requires GCP authentication (compute.disks.create\
    \ API requires an OAuth token). The snapshot is thus exposed to all authenticated GCP principals (allAuthenticatedUsers)\
    \ and, in theory, anyone with GCP credentials (allUsers \u2014 though this is a rare misconfiguration\
    \ pattern). Do not downgrade to ExposedToInternet; GCP auth is a hard requirement."
  derived_from:
  - <snapshot HasPolicy edge>
  - <snapshot IAM getIamPolicy response with allAuthenticatedUsers or allUsers>
  narrative: '{snapshot.name} has an IAM binding granting {principal} read access (compute.snapshots.useReadOnly),
    exposing the snapshot''s contents to all GCP-authenticated identities (or all holders of GCP credentials
    for allUsers). Any GCP-authenticated identity across accounts/projects can create a disk from this
    snapshot and read its data.'
move · open · esc close