Public storage bucket exposures remain one of the most common — and most avoidable — cloud security incidents, and they continue to happen despite being widely known and well documented. This guide provides a specific, step-by-step checklist for auditing and securing S3 buckets and their GCP equivalent, Cloud Storage buckets, going beyond the general overview in our cloud security basics guide.
Step 1: Enable account-wide public access blocking
Before auditing individual buckets, enable the account-wide setting that blocks public access as a default across your entire account — AWS calls this “S3 Block Public Access,” configurable at the account level rather than per bucket. This acts as a safety net that overrides individual bucket-level public access settings, meaning even if someone later misconfigures a specific bucket to be public, the account-wide setting prevents that misconfiguration from actually taking effect.
GCP’s equivalent is enforcing public access prevention at the organization policy level, which similarly overrides individual bucket-level settings. Enable this first, before working through individual buckets, since it provides protection against future mistakes, not just the ones you find during today’s audit.
Step 2: Audit every existing bucket for public access
With the account-wide setting in place, systematically review every existing bucket to identify any that currently have public access configured, even if the account-wide block now prevents that access from being exploitable. Cleaning up individually misconfigured buckets, rather than just relying on the account-wide override, matters because the override itself could later be disabled by someone unaware of why it exists, at which point any still-misconfigured individual buckets become exposed again.
Both AWS and GCP provide console views and CLI commands to list buckets along with their public access configuration, making this a straightforward, if potentially time-consuming, review for an account with a large number of buckets accumulated over time.
Step 3: Replace public access with signed URLs where sharing is genuinely needed
If a bucket was made public specifically to share files with someone outside your organization, replace that configuration with signed URLs instead — time-limited, revocable links generated on demand for a specific file, rather than making the entire bucket permanently public. Both AWS and GCP support generating these signed URLs programmatically or through the console, with a configurable expiration time.
This approach gives you the genuine sharing capability the public bucket was likely trying to solve, without the permanent, unbounded exposure that a fully public bucket creates. For recurring sharing needs, consider building this into your application logic (generating signed URLs on demand) rather than manually generating one-off links each time.

Step 4: Enable encryption at rest
Confirm server-side encryption is enabled for every bucket, ideally as an enforced default for any new bucket created going forward rather than something manually enabled per bucket. Both AWS S3 and GCP Cloud Storage support this with minimal setup and negligible performance impact for the large majority of use cases, and using the provider’s managed encryption keys is sufficient for most small teams unless specific compliance requirements mandate customer-managed keys.
Step 5: Enable versioning for critical buckets
Versioning keeps previous versions of a file when it is overwritten or deleted, providing protection against accidental deletion, an application bug that corrupts data, or a malicious actor attempting to destroy data as part of an attack. For any bucket storing genuinely important data — backups, critical application data, anything that would be costly to lose — enable versioning, understanding that it does increase storage costs somewhat since old versions are retained rather than immediately discarded.
Pair versioning with a lifecycle policy that automatically transitions or deletes older versions after a defined period, balancing the protection versioning provides against the storage costs of retaining every historical version indefinitely.
Step 6: Review and restrict IAM permissions on bucket access
Beyond public access, review which specific users and service accounts have permission to read, write, or delete objects within each bucket, applying the same least-privilege principles covered in our IAM best practices guide. A bucket that is not publicly accessible but has overly broad internal permissions granted to far more users or services than actually need access still represents unnecessary risk.
Step 7: Enable access logging
Enable access logging for buckets containing sensitive data, recording who accessed what and when. This is not enabled by default in most cases and needs to be explicitly configured. Beyond helping investigate an incident after the fact, access logs can also help you identify unexpected access patterns that might indicate a problem — a service account suddenly accessing far more objects than its normal usage pattern, for example.
Step 8: Set up alerts for configuration changes
Rather than relying purely on periodic manual audits, set up automated alerts for high-risk configuration changes to your storage buckets — a bucket’s public access setting being changed, a bucket policy being modified to grant broader access. AWS CloudTrail and GCP’s Cloud Audit Logs both support this, giving your team a chance to catch and reverse an accidental (or malicious) misconfiguration quickly, rather than discovering it during the next scheduled quarterly audit.
Common ways buckets accidentally become public
Understanding how buckets typically end up publicly exposed helps target the audit more effectively. The most common pattern is a developer needing to quickly share a file with someone outside the organization, setting the bucket (or a specific object within it) to public to make sharing easier, and never reverting the setting once the immediate need passed. A second common pattern involves overly broad bucket policies written during initial setup, intended to grant access to a specific internal service, but written using a wildcard or overly permissive condition that inadvertently includes public access as well. A third pattern involves infrastructure-as-code templates or scripts copied from an online example or tutorial that included public access settings appropriate for that example’s specific use case, but never adjusted for a production environment handling genuinely sensitive data.
Recognizing these patterns helps when reviewing your own environment — rather than just checking a binary “is this public” setting, look specifically for recently modified buckets, buckets with unusually broad policy statements, and any buckets created from a template or script that may have carried over settings not intended for your specific use case.
Testing your bucket security configuration
After working through the checklist above, verify the configuration actually behaves as intended rather than assuming the settings took effect correctly. Attempt to access a bucket’s contents directly through its public URL from a browser in an incognito or private window, without being logged into any account with legitimate access — this should fail for any bucket you intend to be private. For buckets where you have configured signed URLs for specific sharing needs, confirm the signed URL works as expected and that it actually expires at the configured time rather than remaining valid indefinitely.
Ongoing maintenance: making this a recurring habit
This checklist is most valuable as a recurring practice, not a one-time cleanup. New buckets get created as projects evolve, and without a consistent process, they can easily be created without the same care applied during this initial audit. Consider building bucket creation templates or infrastructure-as-code configurations that apply these security defaults automatically for any new bucket, rather than relying on each team member remembering to manually apply the checklist every time a new bucket is needed.
Frequently asked questions
How quickly do publicly exposed buckets typically get discovered by attackers?
Automated scanning tools continuously probe for publicly accessible cloud storage across the internet, and in documented incidents, newly exposed buckets have been found and accessed within hours in some cases. This is a strong argument for proactively auditing rather than assuming an exposure will go unnoticed simply because it has not caused a visible problem yet.
Is it ever acceptable to have a genuinely public bucket, like for hosting public website assets?
Yes — some use cases, like hosting publicly accessible website images or static site assets, genuinely require public access. The key distinction is that this should be a deliberate, documented decision for a specific bucket with a clear purpose, not an accidental default or a leftover from a quick fix that was never reverted.
Do we need a third-party tool to manage this, or are the native cloud provider tools sufficient?
For most small teams, the native tools covered in this checklist are sufficient. Third-party cloud security posture management tools become more valuable once your team manages a large enough number of buckets and other cloud resources that manual native-tool review becomes difficult to keep up with consistently.
How often should we repeat this checklist?
Quarterly is a reasonable cadence for most small teams, alongside your broader cloud security review. Any significant new project involving new storage buckets is also a natural trigger to apply this checklist immediately to the new buckets, rather than waiting for the next scheduled review.
For more on securing your broader cloud infrastructure, see our cloud security basics guide and IAM best practices guide.