# GCS Bucket Does Not Enforce Public Access Prevention

> Flags Cloud Storage buckets without enforced public access prevention, so a single allUsers grant can expose their contents.

Source: https://zop.dev/integrations/gcp/recommendations/gcs-bucket-does-not-enforce-public-access-prevention

---

## What enforcement blocks that IAM alone does not

Public exposure of a bucket usually comes from one binding: `allUsers` (anyone on the internet)
or `allAuthenticatedUsers` (any user or service account authenticated with a Google Account) added to the bucket's IAM
policy or an object ACL. Nothing stops that grant unless public access prevention is on.

With it enforced, Google's
[public access prevention page](https://cloud.google.com/storage/docs/public-access-prevention)
describes the behaviour: requests authorised through `allUsers` or `allAuthenticatedUsers` fail
with 401 or 403, attempts to add those principals fail with `412 Precondition Failed`, and
existing public grants stay in the policy but are overridden. It does not affect signed URLs,
which are scoped to a service account.

## Finding buckets that are not enforced

The setting reads either `enforced` or `inherited`:

```bash
gcloud storage buckets describe gs://BUCKET_NAME \
  --format="default(public_access_prevention)"
```

Then look for public principals in the bucket policy:

```bash
gcloud storage buckets get-iam-policy gs://BUCKET_NAME | grep -E "allUsers|allAuthenticatedUsers"
```

## The single setting ZopNight checks

ZopNight reads the bucket's public access prevention value during inventory and fires when it is
anything other than enforced. The finding means the guard rail is missing. It is not proof that a
public binding exists today, which is why the fix starts with checking the IAM policy.

## Buckets that are skipped or already safe

A bucket that was not fully inventoried produces nothing. The rule reads the bucket's own value,
so a bucket showing `inherited` is flagged even when the `storage.publicAccessPrevention`
constraint applies from the project, folder or organization and already protects it. Buckets
deliberately public for static website hosting are a legitimate exception; Google suggests
handling them with a project-level exception rather than leaving everything open.

## Exposure risk rather than spend

No saving is attached; the fixed estimate is $0. The risk is a data breach, which is why the
severity is critical.

## Locking the bucket down

1. Check the IAM policy for `allUsers` and `allAuthenticatedUsers` and find out whether any
   application depends on them. Enforcing prevention will break those readers.
2. Remove any public binding that is not intended.
3. Enforce prevention on the bucket:
   `gcloud storage buckets update gs://BUCKET_NAME --public-access-prevention`.
4. Set the `constraints/storage.publicAccessPrevention` organization policy at the highest level
   you can, so new buckets are covered from creation.
5. If the bucket was public, review its contents and access logs for what may have been read.
