Skip to main content
MisconfigurationHigh

Publicly Accessible Cloud Storage Bucket

A publicly accessible cloud storage bucket is an S3, Google Cloud Storage, or Azure Blob container whose access controls let anyone on the internet list or download its objects without authentication, frequently exposing backups, logs, customer records, or secrets.

Object storage is the quiet backbone of modern infrastructure: it holds your database dumps, application logs, user uploads, and CI artifacts. A bucket is meant to be private by default, but a single permissive ACL grant, a wildcard bucket policy, or a forgotten setting can flip that default and turn the bucket into an open directory anyone can browse. Because storage URLs are predictable and the contents are often the crown jewels, an open bucket is one of the most directly monetizable findings an attacker can stumble onto, and one of the easiest to overlook in a sprawling multi-account cloud estate.

Reviewed by Ameya Lambat

Security Research Contributor, Legba

Reviewed 2026-05-28 · Updated 2026-05-28

What it is

Cloud object storage exposes data as objects inside named containers, called buckets in Amazon S3 and Google Cloud Storage and containers in Azure Blob Storage. A bucket becomes publicly accessible when its access controls grant read (and sometimes list or write) permission to anonymous principals. In S3 this happens through an object or bucket Access Control List (ACL) that grants the predefined AllUsers group, or a bucket policy that allows the Principal wildcard. In Google Cloud Storage it happens by granting an Identity and Access Management (IAM) role such as Storage Object Viewer to the special members allUsers or allAuthenticatedUsers. In Azure it happens when a storage account permits anonymous access and a container is set to a public access level. Listable means an unauthenticated request can enumerate every object key; readable means the object bytes can be downloaded once the key is known. Both are dangerous, and listable buckets are worse because the attacker does not even need to guess key names.

When a storage bucket is public, you are not exposing a service you can patch later; you are exposing the data itself, and you cannot un-disclose bytes that have already been downloaded. OWASP documents this directly under A05:2021 Security Misconfiguration, whose attack scenarios include cloud sharing permissions left open to the internet. The cost is concrete: regulated personal data in an open bucket is a reportable breach under GDPR and most US state laws, complete with notification obligations and fines. Worse, a bucket that is publicly writable, not just readable, lets an attacker tamper with the files you serve. In July 2020 Twilio confirmed that an S3 path hosting its TaskRouter JavaScript SDK had been left readable and writable to anyone on the internet; an opportunistic actor modified the library and injected Magecart-style skimming code that every customer loading that SDK would have executed. The stakes therefore span confidentiality (data theft), integrity (supply-chain poisoning of assets you distribute), and the regulatory and reputational fallout that follows.

At a glance

Typepublic-cloud-storage-bucket
Ports443
ProtocolsHTTPS
Seen onAmazon S3, Google Cloud Storage, Azure Blob Storage, DigitalOcean Spaces, MinIO, Cloudflare R2
SeverityHigh
Updated2026-05-28

How attackers find and exploit it

  • Enumerate candidate bucket names by permuting the target's brand, product names, environment suffixes (dev, staging, prod, backup), and known asset hostnames, then resolving them against the provider's predictable endpoints such as <name>.s3.amazonaws.com, storage.googleapis.com/<name>, and <name>.blob.core.windows.net.
  • Harvest bucket references that are already public: parse the target's HTML, JavaScript bundles, mobile app packages, and CDN configurations for hardcoded storage URLs that reveal real bucket names.
  • Send an unauthenticated GET to the bucket root to test for listing; an HTTP 200 with an XML ListBucketResult (or JSON for GCS) confirms the object index is world-readable.
  • If listing is denied but the bucket exists, attempt to read individual objects by guessing or brute-forcing common key names such as backup.sql, .env, config.json, and dated log prefixes, since a bucket can deny listing yet still serve readable objects.
  • Download exposed objects in bulk to mine them for secrets, credentials, API keys, and personal data, then pivot using any recovered credentials into the wider cloud account.
  • Test for write access by attempting an anonymous PUT of a harmless marker object; a success means the attacker can overwrite served assets, plant malware, or host phishing content under the victim's trusted domain.

How to detect it on your surface

  • Inventory every storage bucket and container across all cloud accounts, subscriptions, and projects, including shadow accounts created outside central provisioning, because you cannot assess what you have not enumerated.
  • For each AWS account, query the account-level and per-bucket S3 Block Public Access configuration and flag any bucket where all four settings are not enabled.
  • Review bucket policies and object ACLs for grants to the AllUsers or AuthenticatedUsers groups in S3, to allUsers or allAuthenticatedUsers in GCS, and for AllowBlobPublicAccess being true on Azure storage accounts.
  • Run an external, unauthenticated check from outside your network against each bucket endpoint to confirm what the public actually sees, rather than trusting the console's status label alone.
  • Cross-check cloud provider findings (AWS Trusted Advisor, S3 access analyzer, GCP Security Command Center, Microsoft Defender for Cloud) against your own inventory to catch buckets the native tools missed.

Detection signals

  • An anonymous GET to the bucket root returns HTTP 200 with an XML body whose root element is <ListBucketResult> (S3) or a JSON listing under items (GCS), proving the contents are enumerable.
  • Object responses carry headers such as x-amz-bucket-region, x-amz-request-id, or x-goog-generation, confirming the endpoint is a live cloud bucket rather than a generic web server.
  • A request to a private bucket returns HTTP 403 AccessDenied with an <Error><Code>AccessDenied</Code> body, while a non-existent bucket returns 404 NoSuchBucket, letting you distinguish existing-but-locked from absent.
  • Azure containers expose the x-ms-blob-public-access response header or return blob content to requests bearing no Authorization header, indicating anonymous access is enabled.
  • An anonymous PUT or DELETE that returns HTTP 200 instead of 403 is a definitive signal that the bucket is not just readable but writable.

Validate before you report

  • Issue an unauthenticated HTTP request, with no credentials, signature, or session, against the bucket listing endpoint and capture the full response code and body to prove anonymity rather than inferring it from a logged-in console view.
  • Confirm the listing actually enumerates keys by parsing the returned <ListBucketResult> or JSON for at least one real object key, distinguishing a truly listable bucket from an empty or redirect response.
  • Fetch one non-sensitive object by key with the same anonymous request to verify that read access resolves to downloadable bytes and not merely a metadata HEAD that returns 403 on GET.
  • Re-test from a clean network egress with no cached cloud identity to rule out that access is actually being granted by an ambient IAM role, VPC endpoint policy, or corporate SSO rather than by true public exposure.
  • Record the evidence (request, response headers, status code, and a redacted sample object key) and the timestamp so the finding is reproducible and defensible, then stop short of bulk-downloading sensitive data.

What looks like this but isn't

  • A bucket fronted by a CloudFront, Cloud CDN, or Azure Front Door distribution may serve content publicly through the CDN via signed origin access while the bucket itself remains private; confirm whether the open access is on the origin bucket or only on the CDN edge.
  • Objects served through time-limited pre-signed or signed URLs are intentionally reachable by anyone holding the URL but are not publicly listable; a 200 on a signed URL is not evidence of a public bucket.
  • Some buckets are deliberately public, such as those hosting static website assets, open-source release artifacts, or public datasets; validate against the asset owner's intent before flagging, and instead check that only non-sensitive objects are reachable.
  • Access granted by your own authenticated egress (an attached IAM role or VPC endpoint) can masquerade as public access when tested from inside the network; always re-test anonymously from outside.

Remediation

  • Immediately enable account-level S3 Block Public Access (all four settings: BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets), enable Public Access Prevention with Uniform Bucket-Level Access in GCS, and set AllowBlobPublicAccess to false on Azure storage accounts.
  • Remove the offending grants: delete AllUsers and AuthenticatedUsers entries from S3 ACLs and any Principal wildcard from bucket policies, and revoke allUsers and allAuthenticatedUsers IAM bindings in GCS.
  • Rotate every credential, API key, token, and secret that was reachable in the exposed objects, treating them as compromised regardless of evidence of access.
  • Review cloud audit logs (S3 server access logs, CloudTrail data events, GCS audit logs, Azure storage logs) to determine which objects were actually downloaded and over what window, to scope breach-notification obligations.
  • Move genuinely public content behind a CDN with origin access control so the origin bucket can stay private, and replace ad hoc public links with short-lived pre-signed URLs.
  • Codify the locked-down configuration in infrastructure-as-code and add a guardrail (Service Control Policy, GCP Organization Policy, or Azure Policy) that prevents the public setting from being re-enabled.

Operational checklist

  • Enforce a default-deny baseline organization-wide so new buckets cannot be made public, using AWS Service Control Policies, GCP Organization Policy constraints, and Azure Policy that deny public access settings.
  • Run continuous external attack-surface monitoring that re-tests every known and newly discovered bucket from an unauthenticated vantage point, not just point-in-time scans.
  • Enable and centrally aggregate access logging and data-event logging for all storage so anonymous reads are visible and alertable.
  • Maintain an authoritative, automatically refreshed inventory of all buckets across every account, project, and subscription, including those in acquired or legacy environments.
  • Classify data so sensitive datasets are tagged and subject to stricter policy, and block sensitive classes from ever residing in a public-capable container.
  • Review IAM and bucket policies on a recurring cadence and alert on any drift that grants anonymous or all-authenticated principals.

What to do next

An open storage bucket is not a theoretical risk; it is your data sitting on the public internet waiting to be indexed, downloaded, or weaponized, as the Twilio SDK compromise showed when a writable S3 path became a supply-chain attack vector. The job a security team actually needs done is not another scanner alert but a confirmed, evidenced finding they can hand to an owner today. Start now: enumerate your buckets, test each one anonymously from outside, and turn on Block Public Access or its equivalent before someone else proves the exposure for you.

Methodology

Each finding-type guide is built from Legba Recon's real detection and validation logic, reviewed by a named security contributor, and cited against primary sources such as OWASP, CISA, NIST, and MITRE. We update pages when the underlying guidance changes. See our contributors and company.

FAQs.

References.

Weakness references (CWE)

Keep exploring

Your agent needs its Legba.

Read the docs