S3-compatible object stores are exactly that: compatible. That means the same ACL semantics, the same API surface, and, critically, the same unauthenticated listing endpoint that makes open AWS S3 buckets trivially discoverable. DigitalOcean Spaces and Wasabi both speak the S3 wire protocol closely enough that tooling written for AWS (from curl to aws-cli to bucket scanners) works against them without modification. The exposure pattern is not similar to S3; it is structurally identical.

How the access model works across S3-compatible stores

S3-compatible stores inherit two key mechanisms from the AWS API: ACLs and bucket policies. The predefined ACLs matter most for public exposure. The private canned ACL is the safe baseline: only the owner has access. The public-read canned ACL grants unauthenticated READ permissions to the world: list the bucket contents, GET any object without credentials.

DigitalOcean Spaces adds a user-interface layer on top of this: a toggle in the Spaces control panel labeled "File Listing: Enabled". It is easy to misread what this does. The toggle controls anonymous listing only. With it enabled, an unauthenticated caller can enumerate the bucket's contents (file names, sizes, modification dates), which is itself a serious metadata leak. It does not, on its own, make every object downloadable: pulling an individual object still requires that object to carry a public-read ACL. The toggle is framed in the UI as a convenience feature for static hosting, which is how it gets flipped in practice: a developer wants to serve a public asset folder, enables file listing, ships the feature, and the Spaces bucket stays listable indefinitely, handing attackers a full index of what is inside.

One caveat: the panel toggle is not a 1:1 mirror of the bucket's ACL state. A bucket policy or ACL set directly through the S3 API can override what the panel shows, so a "File Listing: Disabled" toggle does not guarantee the bucket is actually private. Audit both the panel setting and the underlying S3 ACL/policy.

Wasabi uses the same ACL vocabulary and the same API. There is no equivalent toggle. Exposure comes through the same public-read ACL or an open bucket policy as in standard S3. The control surface looks familiar to anyone who has worked with AWS; the misconfiguration path is equally familiar.

Both providers default to private: a newly created Spaces or Wasabi bucket without an explicit public ACL is inaccessible to anonymous callers. The exposure window opens the first time someone changes that.

Detecting exposure: the listing probe

The S3-compatible ListObjectsV2 endpoint is the detection primitive. Send an unauthenticated GET with the ?list-type=2 query parameter:

GET https://<bucket-name>.<region>.digitaloceanspaces.com/?list-type=2

For Wasabi, use the appropriate regional endpoint:

GET https://s3.<region>.wasabisys.com/<bucket-name>?list-type=2

A 200 response with <ListBucketResult> XML means the bucket is publicly listable. A 403 AccessDenied means listing is blocked for anonymous callers, but object-level reads may still be open if individual objects carry public-read ACLs, so a 403 on the listing probe is not a clean bill of health.

For DigitalOcean Spaces, the control panel is the quickest first-pass audit if you own the bucket: navigate to the Spaces settings panel and check whether "File Listing" is enabled. Treat that as a starting point, not the last word. An S3-API-set policy or ACL can override the toggle, so confirm against the actual ACL too. The API check uses the aws CLI pointed at the Spaces endpoint:

aws s3api get-bucket-acl \
  --bucket <your-bucket-name> \
  --endpoint-url https://<region>.digitaloceanspaces.com

Inspect the Grants array for any entry where Grantee.URI is http://acs.amazonaws.com/groups/global/AllUsers. That group is the anonymous-caller principal in ACL terms; its presence confirms public listing or download access depending on which Permission value appears alongside it.

If you want to check a bucket URL without credentials, paste it into the open-bucket viewer. It runs the listing probe and reports what an anonymous caller can actually reach.

What ends up in open Spaces buckets

The asset categories differ slightly from what leaks from a forgotten AWS bucket, because Spaces attracts a distinct usage pattern. Its native CDN integration makes it the go-to for serving user-uploaded media, static build artifacts, and front-end asset bundles, and that mix turns up reliably in exposed buckets. Much of it is user-generated content: profile photos, document uploads, videos from customer workflows, the kind of data that is often personally identifiable and regulated under privacy law. Alongside it sit front-end build outputs: JavaScript bundles, configuration files, and, most dangerously, source maps, which reconstruct server-side application logic straight from minified code. Teams also use Spaces as a cheap backup destination, so database dumps and application-state archives written there routinely carry credentials and connection strings. Internal CI/CD artifacts round out the mix, material meant to be reached over a VPN, not the open internet.

A public-read ACL on a bucket holding source maps and CI artifacts hands an attacker a reconstruction of the application codebase with no exploit required.

Remediation

DigitalOcean Spaces. The fastest fix for File Listing is the Spaces control panel: toggle "File Listing" back to Disabled. That change goes into effect immediately and removes the unauthenticated listing grant. For object-level ACLs that may have been set to public-read individually, there is no bulk UI toggle. Audit and reset them via the API or aws-cli pointed at the Spaces endpoint:

# List all objects and their ACLs
aws s3api list-objects-v2 \
  --bucket <bucket-name> \
  --endpoint-url https://<region>.digitaloceanspaces.com \
  --query 'Contents[*].Key' \
  --output text | tr '\t' '\n' | \
  xargs -I{} aws s3api get-object-acl \
    --bucket <bucket-name> \
    --key {} \
    --endpoint-url https://<region>.digitaloceanspaces.com

For any object where Grantee.URI maps to AllUsers, reset it to private:

aws s3api put-object-acl \
  --bucket <bucket-name> \
  --key <object-key> \
  --acl private \
  --endpoint-url https://<region>.digitaloceanspaces.com

Wasabi. The same ACL and bucket policy audit procedure applies. Use the aws CLI with Wasabi's regional endpoint substituted. Wasabi's IAM model is a close analog of AWS IAM for buckets and policies; any public ACL or wildcard-principal bucket policy should be removed.

For public-facing assets, serve through the Spaces CDN instead of an open bucket. The Spaces CDN edge is designed to front a private Space: you enable the CDN on the Space, and it serves objects through the .cdn.digitaloceanspaces.com edge without the bucket itself having to be publicly listable or carry public-read ACLs. Keep the Space private and let the CDN be the only public surface. For anything user-specific or access-controlled, don't serve it from the CDN at all. Generate a time-limited signed URL against the origin Spaces endpoint via the S3 presign API, so each object is reachable only for the lifetime of its token.

Wasabi. Wasabi does not implement the S3 PublicAccessBlock / Block Public Access feature, so there is no BPA switch to fall back on. Buckets are private by default, and as of 2023-03-13 Wasabi tightened public access: accounts created after that date cannot enable public access through the console or CLI at all, requiring a support request to Wasabi. Older, pre-2023 accounts still expose a per-bucket "Public Access" override in the console, which is where the easy public-ACL path mostly lives. On a newer account, an accidental public bucket is hard to create in the first place; on an older account, that per-bucket override and any wildcard-principal bucket policy are the two things to audit and lock down.


For an index of exposed DigitalOcean Spaces buckets found by this service, see the DigitalOcean provider index. For Wasabi exposures, see the Wasabi exposure index. To probe a specific bucket URL right now, use the open-bucket viewer.