Point-in-time remediation has a failure mode that teams discover the hard way: they fix the open bucket, check it off, and six months later a different bucket (created by a new team, spawned by a Terraform module, or copied from an old template) is open again. The root cause isn't a one-time misconfiguration; it's a process that treats security as a snapshot rather than a steady state. Cloud storage access control drifts, and the only reliable defense against drift is detection that runs continuously.

Why fixed configurations regress

New buckets inherit old patterns. When a developer creates a new bucket, they often start from the same template or copy-paste the CLI invocation that previously worked. If the original configuration had a permissive ACL or a public-read bucket policy, the copy carries that forward. Infrastructure-as-code makes this worse in one direction and better in another: a misconfigured Terraform module replicates the same mistake across every environment it provisions, but it also means a correctly audited module prevents future drift if it's the only path to bucket creation.

ACL drift happens without touching the bucket. S3 bucket policy and ACL changes can be made by any IAM principal with s3:PutBucketPolicy or s3:PutBucketAcl permission on the bucket. In accounts with loose IAM policies, common in fast-moving engineering teams where developer access is broad, a misconfiguration can slip in during a debugging session, a one-off data migration, or an automated process written with overly permissive defaults and never audited.

Organizational growth outpaces manual review. A team managing five buckets can reasonably audit them by hand. A team managing five hundred cannot. Without automated detection, the buckets that get fixed are the ones that triggered an incident; the ones that remain misconfigured are the ones nobody has checked yet.

Per-provider native detection controls

AWS S3

AWS Config is purpose-built for catching ACL and policy drift: the cases where a bucket was fine yesterday and misconfigured today because someone ran a one-off CLI command or an automated process applied overly permissive defaults.

AWS Config managed rules. The s3-bucket-public-read-prohibited managed rule evaluates every S3 bucket in the account and reports any bucket where anonymous read access is permitted, through either ACLs or bucket policies. The companion rule s3-bucket-public-read-write-prohibited covers write access. Both rules evaluate continuously as bucket configurations change, not just on a schedule, which means a newly introduced permissive policy triggers a compliance finding within minutes.

Config rules can be wired to auto-remediation via AWS Systems Manager Automation. When a rule violation is detected, an SSM runbook runs automatically to correct the bucket's Block Public Access settings, turning detection into automatic correction.

CloudTrail on mutating bucket events. AWS CloudTrail records every API call against S3 bucket configuration. The events that change access control are:

  • PutBucketAcl: changes the bucket-level ACL
  • PutBucketPolicy: installs or modifies a bucket policy
  • DeleteBucketPolicy: removes a bucket policy (can re-expose a bucket that relied on policy restrictions)
  • PutBucketPublicAccessBlock: changes Block Public Access settings

Alerting on these four events in EventBridge gives real-time notification of any access-control change. Combined with Config's evaluation of the resulting state, you get both immediate change notification and confirmation of whether the change introduced a violation.

Azure Blob Storage

Azure Policy's strongest value is prevention: it blocks non-compliant storage accounts from being created in the first place, rather than finding problems after the fact.

Azure Policy. Use the GA built-in policy "Storage account public access should be disallowed (block anonymous blob access)", which evaluates storage accounts against the allowBlobPublicAccess property. Assign it at the subscription or management group level for coverage across all storage accounts regardless of where they were created. (Avoid the [Preview]: Storage account public access should be disallowed policy. It has a known logic inversion that causes backwards compliance reporting.)

Set the effect to deny rather than audit: deny blocks any storage account from being created or modified with public blob access enabled, closing the misconfiguration window before it opens.

Microsoft Defender for Storage. For accounts with Defender for Storage enabled, anomalous access patterns on blob containers (including unexpected public access and unusual enumeration activity) generate security alerts in Microsoft Defender for Cloud. Policy prevents misconfiguration; Defender detects suspicious activity even when configuration appears correct.

Google Cloud Storage

GCS organization policy is the most preventive of the three. It eliminates the entire class of public-bucket exposure at the org level, including ACLs and pre-existing public grants, before any team or project can create one.

GCS Organization Policy. The constraints/storage.publicAccessPrevention organization policy, when set to enforced, prevents any bucket in the organization from having allUsers or allAuthenticatedUsers bindings. Crucially, it overrides pre-existing public grants too, not just new ones. It covers both IAM bindings and legacy ACLs, and it applies automatically to every project created under the org node going forward. This is the GCS equivalent of AWS account-level Block Public Access, but with retroactive force.

Set the constraint via the gcloud CLI:

gcloud resource-manager org-policies enable-enforce \
  constraints/storage.publicAccessPrevention \
  --organization=<org-id>

GCS log-based alerts in Cloud Logging. Cloud Audit Logs records GCS admin activity, including storage.buckets.setIamPolicy (the event that fires when an IAM binding is added or changed on a bucket). A log-based alert in Cloud Monitoring on this event, filtered to changes that include allUsers or allAuthenticatedUsers as the member, gives real-time notification when a bucket IAM policy grants public access. This serves as a second layer in projects where the org policy is not yet enforced.

The alerting filter:

resource.type="gcs_bucket"
protoPayload.methodName="storage.buckets.setIamPolicy"
protoPayload.request.policy.bindings.members=~"allUsers|allAuthenticatedUsers"

External and continuous monitoring as a control layer

Provider-native controls are reliable within the cloud account they're configured in. They don't cover buckets created outside the core security program, and they can't account for what happens when a bucket name leaks through a JavaScript bundle, a git commit, or a third-party integration and gets indexed by external scanners.

External continuous monitoring watches for the same signals an attacker would find: open bucket listings that respond to unauthenticated probes, company-related bucket names appearing in public indexes, and exposed object names or content referencing brand assets or customer data. That measures actual attacker-visible exposure, not just configuration state as the cloud provider sees it.

The practical gap is concrete. Internal detection tells you when your Terraform module creates a misconfigured bucket. External monitoring tells you that the bucket a contractor created in a personal AWS account, fronting a subdomain of your brand, has been open for three months and its contents are appearing in search results.

For organizations with multiple cloud accounts, acquired product lines, or contractor- managed infrastructure, external monitoring fills coverage gaps that internal controls simply cannot reach. See the enterprise monitoring plans for the brand-asset monitoring controls this service provides on a continuous basis.


For a full index of exposed buckets tracked across all providers, see the provider index. To probe a specific bucket URL right now, use the open-bucket viewer. For teams evaluating continuous brand-asset monitoring, see enterprise monitoring.