# GCS Bucket Uniform Access Not Enabled

> Uniform bucket-level access replaces per-object ACLs with IAM alone; with it off, 2 permission systems answer "who can read this object" and audits must check both. ZopNight raises medium-severity RC-1232 when the discoverer does not record uniform_bucket_level_access_enabled=true on an enriched bucket. Enabling it stays reversible for 90 days.

Source: https://zop.dev/integrations/gcp/recommendations/gcs-bucket-uniform-access-not-enabled
Updated: 2026-08-19

---

## Two permission systems on one bucket

With uniform bucket-level access disabled, a GCS bucket answers access questions through two
independent mechanisms: IAM policies on the bucket, and legacy ACLs that can differ on every
single object. The practical consequence is that no bucket-level review is conclusive. You
can audit the IAM policy, find it perfectly scoped, and still have one object among millions
carrying a `READER` ACL for `allUsers`, granted years ago by a tool that defaulted to
object-level sharing. Every exposure investigation then becomes an object-by-object walk,
and every access-control statement to an auditor has to be hedged with "plus whatever the
ACLs say."

Uniform access removes the second system. ACLs stop being evaluated, IAM becomes the single
source of truth, and "who can access this bucket" is once again a question with one answer.
Google recommends it for new buckets, and Public Access Prevention composes cleanly with it:
PAP blocks public IAM grants, uniform access guarantees there is no ACL side channel left to
check.

## Migration risk is real but bounded

The one legitimate reason to hesitate is a workload that actually depends on per-object
ACLs, typically multi-tenant patterns where each object is shared with a different
principal. Enabling uniform access on such a bucket breaks those reads. Two things bound the
risk: Cloud Audit Logs can show whether ACL-dependent access is happening at all, and the
switch is reversible for 90 days after enabling, so a mistake is recoverable rather than
fatal. After 90 days the ACL data is gone and the change is permanent. Migrate the sharing
model to IAM conditions or separate prefixes first, then flip the switch.

## One field to check, one flag behind the finding

```bash
gcloud storage buckets describe gs://BUCKET \
  --format="value(uniform_bucket_level_access)"
```

`False` (or empty) reproduces what ZopNight saw. The discoverer derives the signal from
`iamConfiguration.uniformBucketLevelAccess.enabled` and writes
`uniform_bucket_level_access_enabled=true` into metadata only when it is on, never an
explicit false. The rule fires when the key is missing on a bucket that carries the
`storage_class` anchor stamped by the same enricher; without that anchor the resource is
treated as un-enriched and skipped. Reading the configuration requires only
`storage.buckets.get`; flipping the setting is a deliberate, human `gcloud storage buckets
update gs://BUCKET --uniform-bucket-level-access`. Nothing in ZopNight changes bucket
security posture automatically.
