Public Access Settings Compared: S3, Azure Blob, GCS

Exposed object storage is usually the work of a permission nobody revisited, not a clever intrusion. The highest-leverage check you can run this week sits above the buckets themselves: the account-level public access settings in each cloud. In AWS that is S3 Block Public Access, in Azure it is the allowBlobPublicAccess flag on the storage account, and on Google Cloud it is Public Access Prevention. All three are designed to override per-resource permissions: when settings at different levels disagree, Amazon S3 applies the most restrictive combination of the access point, bucket, and account settings, so an account or organization boundary can protect every bucket underneath it. Turn each switch on first, then audit the exceptions. If any switch is off, every bucket, container and project under it needs manual review before you can call the estate covered.
Three Switches, Three Enforcement Models
AWS applies Block Public Access at multiple levels — organization, account, bucket and access point — through a set of independent settings such as BlockPublicAcls, IgnorePublicAcls and BlockPublicPolicy. AWS recommends turning on all of the settings at the account level, which covers all current and future buckets and applies globally across AWS Regions. The strictest applicable level wins: a bucket whose own settings are relaxed stays protected whenever the account or organization level blocks public access.
Azure splits the decision in two. An Azure Resource Manager storage account disallows anonymous access by default, and a user can only open a container to the public when the account permits it. When anonymous access is disallowed for the storage account, Azure Storage rejects all anonymous read requests against blob data, and the account setting overrides whatever an individual container was configured to allow. Azure Policy adds an enforcement layer on top: a policy with a Deny effect refuses to create or modify any storage account whose anonymous access setting is not compliant, so exceptions must be justified at assignment time rather than discovered later.
Google Cloud exposes Public Access Prevention as a bucket setting (enforced or inherited) and as the storage.publicAccessPrevention organization policy constraint at project, folder or organization level. When the setting is enforced, no one can make data in applicable buckets public through IAM policies or ACLs; existing grants to allUsers stay attached to the resource but stop working, which means that if enforcement is ever lifted the old exposure resurfaces immediately — a good reason to delete legacy public grants instead of relying on the override forever. Enforcement is strongly consistent on read-after-write but not instantaneous, and objects cached on the internet can remain publicly readable until their Cache-Control window expires.
| Provider | Safeguard | Where it applies | Override behavior | Finding signal |
|---|---|---|---|---|
| AWS | S3 Block Public Access | Organization, account, bucket, access point | Most restrictive level wins; covers future buckets | Access Analyzer for S3 findings |
| Azure | allowBlobPublicAccess = false | Storage account; Azure Policy can deny exceptions | Account setting overrides container public access | Anonymous-auth metrics and logs |
| Google Cloud | Public Access Prevention | Bucket setting or org policy constraint | Public grants remain but are overridden while enforced | Cloud Asset Inventory policy queries |
What Each Switch Misses
No account-level switch covers authenticated misuse. AWS explicitly warns that Block Public Access does not inspect identity-based policies on your IAM roles or resource-based policies on related resources such as KMS keys, so an over-permissive principal can still widen access to data that is formally private. In Azure, the flag governs anonymous requests only: a request that arrives with an Authorization header is evaluated against the presented credentials, and signed access is a separate review track. On Google Cloud, signed URLs keep working regardless of Public Access Prevention, which is the right behavior for time-limited sharing but means your inventory must also track how URL issuance is governed. Plan exceptions before enforcing: static website hosting is the case every vendor documents a supported path for, and an approved-hosting project is cleaner than an estate-wide weakening.
Quarterly Cross-Cloud Review Procedure
- Export the inventory: every S3 bucket, Azure storage account and GCS bucket, from Cloud Asset Inventory or your provisioning state — never from memory.
- Record the safeguard state per resource — Block Public Access flags, allowBlobPublicAccess, publicAccessPrevention — plus the account and organization layers above each one.
- Flag every resource where any layer is off. Each exception gets an owner, a written reason and an expiry date; no silent exceptions.
- Cross-check guardrails so the switches cannot be quietly disabled, pairing account-level settings with SCP restrictions as covered in 6 AWS SCP guardrails that contain a compromised account.
- Reconcile last quarter’s exception list: expired entries get closed, renewed entries get re-justified by the data owner.
- Publish the summary — counts, deltas, open exceptions — to the team that owns the data, not only to the security queue.
Reading the Detection Signals
Configuration checks catch standing exposure; signals catch drift between reviews. IAM Access Analyzer for S3 flags buckets granting public access, reporting the source and level of the grant whether it lives in an ACL, a bucket policy or an access point policy. In Azure, build a Metrics Explorer view filtered to Authentication = Anonymous to see the volume of anonymous requests, then confirm which containers are involved with a StorageBlobLogs query on AuthenticationType == Anonymous — a nonzero count after anonymous access was disallowed means something is still publishing public endpoints. Google Cloud has no single equivalent alert, so query bucket IAM policies through Cloud Asset Inventory and treat any allUsers grant on a bucket that is not an approved website host as a finding. Feed these results into your wider logging practice so exposure events are triaged alongside the detections that matter in your logging baseline.