gcp-gcs-read-data
storage.objects.get constitutes effective data-plane read access to GCS objects in the bucket (permission applies at object level but IAM bindings are bucket-scoped).
match (effective permission)
{
"action": "storage.objects.get",
"resource_type": "google.storage.Object"
}
where
bucket is NOT CMEK-encrypted (defaultKmsKeyName unset, or all objects use Google-managed keys) — for CMEK buckets see gcp-gcs-read-data-cmek
emit
| source type | Identity |
|---|---|
| target type | Storage |
| source | <principal> |
| target | <GCS Bucket / ObjectStorage node> |
| permissions | storage.objects.get |
| conditions | iam_permission resource_policy |
| state logic | ACTIVE when storage.objects.get is confirmed effective at the bucket (IAM allow policy, UBLA, and predefined ACL layers unified) and no VPC-SC perimeter blocks the storage API for the caller; CONDITIONAL(resource_policy) when UBLA is disabled and object-level ACLs may restrict individual objects; BLOCKED when a VPC-SC perimeter, org policy (constraints/gcp.storageForcePublicAccessPrevention), or IAM deny explicitly blocks storage.objects.get for this caller. |
Narrative
{principal.name} holds storage.objects.get on bucket {bucket.name} and can read the content of any object in the bucket.
Raw rule rules/derived/gcp/gcs.yaml
id: gcp-gcs-read-data
emits: CanReadData
description: storage.objects.get constitutes effective data-plane read access to GCS objects in the bucket
(permission applies at object level but IAM bindings are bucket-scoped).
match_effective_permission:
action: storage.objects.get
resource_type: google.storage.Object
where:
- "bucket is NOT CMEK-encrypted (defaultKmsKeyName unset, or all objects use Google-managed keys) \u2014\
\ for CMEK buckets see gcp-gcs-read-data-cmek"
emit:
source_type: Identity
target_type: Storage
source: <principal>
target: <GCS Bucket / ObjectStorage node>
permissions:
- storage.objects.get
conditions:
- iam_permission
- resource_policy
state_logic: ACTIVE when storage.objects.get is confirmed effective at the bucket (IAM allow policy,
UBLA, and predefined ACL layers unified) and no VPC-SC perimeter blocks the storage API for the caller;
CONDITIONAL(resource_policy) when UBLA is disabled and object-level ACLs may restrict individual objects;
BLOCKED when a VPC-SC perimeter, org policy (constraints/gcp.storageForcePublicAccessPrevention),
or IAM deny explicitly blocks storage.objects.get for this caller.
confidence: min(contributing_confidences) * 0.97
derived_from:
- storage.objects.get effective permission on bucket
false_positive_note: "storage.objects.list (without get) provides only object metadata (names, sizes,\
\ kmsKeyName) \u2014 NOT content. Do NOT emit CanReadData from list alone. storage.objects.get is\
\ an OBJECT-level permission (applies to individual objects); however, IAM bindings granting this\
\ permission are typically set at the BUCKET scope, covering all objects within the bucket. When UBLA\
\ is enabled, bucket-level IAM is authoritative. When UBLA is disabled, object-level ACLs may restrict\
\ individual objects even if the bucket IAM policy grants read \u2014 downgrade to CONDITIONAL(resource_policy)\
\ in that case and note that fine-grained object ACLs may limit scope. VPC-SC perimeters that include\
\ storage.googleapis.com in the restricted services set block callers outside the perimeter -> BLOCKED(resource_policy).\
\ Public access prevention (org policy constraints/gcp.storagePublicAccessPrevention or bucket-level\
\ publicAccessPrevention) blocks allUsers reads but does NOT affect authenticated callers \u2014 do\
\ not confuse the two."
narrative: '{principal.name} holds storage.objects.get on bucket {bucket.name} and can read the content
of any object in the bucket.'