GCP Storage Bucket Analyzer

Check a Cloud Storage bucket for the access that does not appear in an IAM audit: per-object ACLs alongside IAM, public access prevention left inherited, and allAuthenticatedUsers, which is not your users.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Check the bucket. Nothing leaves this tab.

Wanted a different tool?

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

Public, and invisible in the IAM policy

Uniform bucket-level access off means per-object ACLs apply alongside IAM, and an ACL grant does not appear in an audit of bindings

{"name":"my-uploads","storageClass":"STANDARD","iamConfiguration":{"uniformBucketLevelAccess":{"enabled":false},"publicAccessPrevention":"inherited"},"versioning":{"enabled":true},"acl":[{"entity":"allUsers","role":"READER"}]}

allAuthenticatedUsers, which is not your users

Everyone with a Google account. It reads like a restriction, which is what makes it worse than allUsers.

{"name":"reports","storageClass":"STANDARD","iamConfiguration":{"uniformBucketLevelAccess":{"enabled":true},"publicAccessPrevention":"inherited"},"versioning":{"enabled":true},"bindings":[{"role":"roles/storage.objectViewer","members":["allAuthenticatedUsers"]}]}

A cold class on churning data

Nearline bills a 30 day minimum whether the object stays or not, and with versioning on each new version starts its own

{"name":"cache","storageClass":"NEARLINE","iamConfiguration":{"uniformBucketLevelAccess":{"enabled":true},"publicAccessPrevention":"enforced"},"versioning":{"enabled":true},"softDeletePolicy":{"retentionDurationSeconds":604800},"logging":{"logBucket":"l"}}

A locked retention policy

Locking cannot be undone. Nothing can be deleted before the period, by anyone, including an organisation administrator.

{"name":"audit","storageClass":"STANDARD","iamConfiguration":{"uniformBucketLevelAccess":{"enabled":true},"publicAccessPrevention":"enforced"},"versioning":{"enabled":true},"softDeletePolicy":{"retentionDurationSeconds":604800},"logging":{"logBucket":"l"},"retentionPolicy":{"retentionPeriod":"220752000","isLocked":true}}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Auditing the IAM policy and calling the bucket private

    Without uniform bucket-level access, per-object ACLs apply as well, and an ACL grant is invisible from the IAM policy. A single object can be public while the bucket's bindings grant nothing at all.

    Instead:Turn uniform bucket-level access on, which disables ACLs entirely. Check for objects relying on one first, because they stop being readable.

  2. Leaving publicAccessPrevention inherited

    Inherited follows an organisation policy that may not exist, and then nothing stops a public grant. Enforced blocks allUsers and allAuthenticatedUsers regardless of IAM or ACLs, and the attempt fails rather than succeeding quietly.

    Instead:Set it to enforced on any bucket that should never be public, which is most of them.

  3. Granting allAuthenticatedUsers instead of allUsers

    It is everyone with a Google account, which is most of the internet with an extra step. It reads like a restriction, and that is what makes it worse: somebody chose it believing it meant their own organisation.

    Instead:Grant the specific principals. If the content is genuinely public, serve it through a load balancer with its own controls.

  4. Enabling versioning and calling it protected

    Versioning covers an overwrite and soft delete covers a delete. They are separate features and a bucket needs both, because a truncated file written over a good one and an accidental delete are different mistakes.

    Instead:Enable both, and add a lifecycle rule with numNewerVersions so old versions expire rather than accumulating forever.

  5. Putting a frequently overwritten bucket in a cold class

    Nearline is a 30 day minimum, coldline 90, archive 365, billed whether the object stays or not. With versioning on this compounds: each new version is a new object and the old one starts its own minimum.

    Instead:Use STANDARD for anything that changes, and reserve the cold classes for write-once data.

A bucket has two access systems and the console shows one

Without uniform bucket-level access, per-object ACLs apply alongside IAM. An audit of the IAM policy then sees nothing wrong about an object that is public.

Uniform bucket-level access removes the invisible half

With it off, a single object can carry an ACL making it readable by anyone while the bucket's IAM policy grants nothing at all. Objects also inherit a default ACL at upload, so an object written by a client library can be public without anything in the bucket's configuration saying so. Turning uniform access on disables ACLs entirely, which is the only way to have one answer to who can read this.

gcloud storage buckets update gs://BUCKET \
  --uniform-bucket-level-access

Objects relying on an ACL stop being readable
the moment it is on. Check for those first.

Public access prevention outranks both

Set to enforced, allUsers and allAuthenticatedUsers cannot be granted at all: an attempt fails rather than succeeding quietly, whatever an IAM policy or an ACL says. Left inherited, it follows an organisation policy that may not exist, and then nothing stops a public grant. It is one API call and it closes the whole class.

allAuthenticatedUsers is not your users

It is everyone with a Google account, which is most of the internet with an extra step. It reads like a restriction, and that is what makes it worse than allUsers: somebody chose it believing it meant their own organisation. Both are equally public in any way that matters.

Versioning and soft delete cover different mistakes

Versioning covers an overwrite, which is the shape of most accidental data loss: a job writes a truncated file over a good one. Soft delete covers a delete. A bucket needs both to survive an ordinary afternoon, and neither is on by default on an older bucket.

A locked retention policy is genuinely permanent

Locking cannot be undone. Objects cannot be deleted before the retention period, and the bucket cannot be deleted while it holds any, by anyone, including an organisation administrator. That is the point for a compliance hold and it is worth being certain about, because the only way out is waiting. The period can be extended and never reduced.

The cold classes have a minimum you pay either way

Nearline is 30 days, coldline 90, archive 365. Deleting or overwriting before that is billed for the remainder anyway. With versioning on this compounds: a new version is a new object and the old one starts its own minimum, so a frequently overwritten bucket in a cold class costs far more than its storage figure suggests.

NEARLINE   30 days
COLDLINE   90 days
ARCHIVE   365 days

A lifecycle rule that archives at day 30 and
deletes at day 60 pays for 365 days of archive.

What this cannot see

The objects. Without uniform bucket-level access an individual object can carry its own ACL, and that is not in the bucket document, so a bucket that looks closed here can still be serving something public. It also cannot see organisation policies above the bucket, which may already enforce public access prevention regardless of what this says, and it cannot see who holds the IAM roles it reports. For the objects, gcloud storage objects list with a full ACL listing is the check.