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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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. |
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.'