GCS buckets where Public Access Prevention is not enforced
What does ZopNight detect here?
ZopNight flags any GCS bucket whose iamConfiguration.publicAccessPrevention is not enforced, rating it critical (RC-138). The signal proves prevention is off, not that an allUsers grant exists, since no producer reads the bucket's IAM bindings. The fix is enforcing PAP first, then auditing bindings for public grants.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-138 |
| Category | compliance |
| Severity | critical |
| Metric | none — pure configuration read |
| Source | bucket_public.go |
Where it applies
What the evidence actually proves
Public Access Prevention is the bucket setting that makes allUsers and
allAuthenticatedUsers grants impossible. ZopNight’s discoverer reads
iamConfiguration.publicAccessPrevention during asset inventory and records whether it is
enforced. The rule fires when it is not, and that is precisely all it proves. Nobody has
inspected the bucket’s IAM policy, so the finding does not say “this bucket is public”. A
bucket with PAP off and a clean policy leaks nothing today; what it lacks is the guardrail
that stops one mistaken binding from publishing the contents tomorrow.
An earlier version of this rule claimed a confirmed allUsers binding. The claim was
stronger than the evidence, so the recommendation was rewritten to match what the discoverer
can prove: prevention is not enforced. The distinction matters when you triage: the finding
is a missing safety interlock, rated critical because public GCS buckets remain one of the
most common causes of cloud data breaches, not an alarm that exposure has already occurred.
Enforce prevention, then look for grants
Fixing individual bindings without turning on prevention leaves the door unlocked. The effective order is the reverse:
- Enforce PAP on the bucket (existing public grants become inert immediately).
- Then audit and delete any
allUsers/allAuthenticatedUsersmembers from the policy. - Project-wide, set the org policy
constraints/storage.publicAccessPreventionso new buckets inheritenforcedand the class of finding stops recurring.
If the bucket genuinely serves a public website, mark the exception deliberately. Do not
leave PAP as inherited by accident.
Verify a bucket from your terminal
gcloud storage buckets describe gs://BUCKET \ --format="value(iamConfiguration.publicAccessPrevention)"enforced is compliant. inherited means the bucket relies on whatever the org policy says,
which, absent that policy, is nothing.
When the rule stays silent
Detection fires only on the discoverer’s explicit public_access_enabled flag being true. A
bucket that was never enriched, with the metadata key absent entirely, is skipped rather than
flagged, so the rule abstains on incomplete data instead of guessing. Discovery itself needs
only read access: bulk inventory under roles/cloudasset.viewer, with per-bucket enrichment
via storage.buckets.get. There is no automated remediation; the change is one console
toggle or a single gcloud storage buckets update --public-access-prevention away, and both
are auditable in the project’s activity log.