Safeguard
Vulnerability Analysis

S3 bucket misconfiguration vulnerabilities explained

S3 misconfigurations have exposed hundreds of millions of records in breaches from Deep Root Analytics to Capital One. Here's how they happen and how to catch them.

Vikram Iyer
Cloud Security Engineer
6 min read

An S3 bucket misconfiguration vulnerability is a security weakness in how an Amazon S3 storage bucket's access controls, encryption, or policies are set up, one that lets unauthorized users read, write, or delete data that was never meant to be public. It is not a flaw in AWS's infrastructure; S3 buckets are private by default. The vulnerability is introduced by whoever configures the bucket: an overly permissive ACL, a bucket policy with a wildcard principal, public access settings left enabled, or a "Block Public Access" toggle someone switched off to unblock a deploy. Because S3 is the default object store behind so much application logic — static assets, backups, logs, ML training data, database dumps — a single misconfigured bucket can expose millions of records in one request, no exploit chain required. Security researchers and automated scanners have found these buckets sitting open for months at a time, and attackers now scan for them continuously.

What exactly counts as an S3 bucket misconfiguration?

An S3 bucket misconfiguration is any deviation from least-privilege access that lets unintended parties read, list, or modify bucket contents or metadata. The most common variants are: public-read or public-write ACLs granted to "Authenticated Users" (which AWS defines as any AWS account holder, not your users) or "All Users"; bucket policies with "Principal": "*" and no condition block; disabled server-side encryption on buckets holding regulated data; missing S3 Block Public Access settings at the account or bucket level; world-listable buckets that leak object keys even when objects themselves require auth; and unauthenticated access to versioned objects that were "deleted" but remain retrievable through prior versions. Terraform and CloudFormation templates copied from tutorials frequently ship with acl = "public-read" hardcoded, and that default survives into production far more often than teams expect.

How do attackers actually find exposed S3 buckets?

Attackers find exposed S3 buckets by brute-forcing predictable bucket names against S3's public DNS naming scheme, since bucket names are globally unique and often mirror company or project names. Tools like Grayhat Warfare, S3Scanner, and bucket_finder have indexed hundreds of thousands of open buckets by combining company names, common suffixes (-backup, -prod, -logs, -assets), and permutations pulled from Certificate Transparency logs and GitHub commits. Because https://bucket-name.s3.amazonaws.com requires no authentication to test, an attacker can enumerate thousands of candidate names per minute and simply check which ones return a 200 instead of a 403. Security researcher Aidan Steele documented in 2021 that S3 bucket enumeration tools were finding tens of thousands of exposed buckets containing everything from source code to unencrypted database backups. This is reconnaissance with almost no cost or risk to the attacker, which is why exposed buckets get found and scraped within hours of going public in many documented cases.

What are the most damaging real-world breaches caused by S3 misconfigurations?

The most damaging S3 misconfiguration breaches have exposed hundreds of millions of records through nothing more than a public bucket policy. In June 2017, UpGuard researchers found a misconfigured S3 bucket belonging to Republican data firm Deep Root Analytics that exposed 198 million US voter records — roughly 1.1 terabytes of personal data — left completely public with no password. That same July, UpGuard disclosed that a Verizon partner, NICE Systems, had exposed call and account records for 14 million Verizon subscribers via an open S3 bucket. Dow Jones exposed account data for 2.2 million customers, including partial credit card numbers, through a bucket configured for "Authenticated Users" access, which UpGuard's Chris Vickery pointed out effectively meant "any AWS user on Earth." WWE exposed personal details of 3 million fans in the same period. And in 2019, the Capital One breach — 106 million customers' data taken, including 140,000 Social Security numbers — began with a misconfigured web application firewall that let the attacker use SSRF to pull temporary credentials from the EC2 instance metadata service, which she then used to list and exfiltrate data from more than 700 S3 buckets and folders.

Why do S3 misconfigurations keep happening despite AWS's default protections?

S3 misconfigurations persist because defaults get overridden faster than they get reviewed, and access controls in S3 are additive across several independent layers that are easy to lose track of. AWS enabled Block Public Access by default for all new buckets starting in April 2023, but every bucket created before that date, plus any bucket where a developer explicitly disabled the setting to make a CI pipeline or CDN integration work, is unaffected. A bucket's effective permissions are the union of its ACL, its bucket policy, any IAM policies attached to roles that can assume access, and the account-level Block Public Access configuration — a change in any one layer, made without checking the others, can silently open access. Skyhigh Networks (later McAfee) reported in its 2017 Cloud Adoption and Risk Report that 7% of all S3 buckets it scanned across enterprise customers had unrestricted public access, and 35% had no encryption enabled at all, numbers that tracked closely with the wave of breaches that same year. Infrastructure-as-code makes this worse at scale: a single Terraform module with a public-read default, reused across 40 microservices, turns one bad copy-paste into 40 exposed buckets.

How can a security team tell if their own S3 buckets are exposed right now?

A security team can determine bucket exposure by running AWS's own s3:GetBucketAcl, s3:GetBucketPolicyStatus, and s3:GetBucketPolicy checks against every bucket in every account, since AWS Config and IAM Access Analyzer both flag buckets whose policy allows access from outside the account. AWS Trusted Advisor and Amazon S3's built-in "Public" indicator in the console will surface obviously public buckets, but they miss conditional exposure — for example, a bucket that's private by ACL but has a Lambda function or CloudFront OAI misconfigured to serve objects to anyone who guesses the object key. External verification matters too: unauthenticated tools like S3Scanner or a simple curl against the bucket's virtual-hosted-style URL will show what an outside attacker sees, independent of what your own IAM policies claim. Any bucket holding PII, credentials, source code, or backups should also be checked for versioning combined with public access, since "deleted" sensitive files often remain retrievable through old object versions that inherited the same permissive policy.

How Safeguard Helps

Safeguard identifies S3 misconfiguration risk as part of its cloud and code-to-cloud scanning, then uses reachability analysis to tell you whether a flagged bucket policy or IAM role actually exposes data your running services touch — not just whether a rule matches a misconfiguration pattern. Griffin AI correlates the bucket's exposure with the SBOM Safeguard generates or ingests from your build pipeline, so you can see which application, service, or third-party dependency writes to or reads from the affected bucket, and prioritize the ones tied to production data over dead infrastructure. For confirmed issues — a public ACL, a missing Block Public Access setting, an overly broad bucket policy — Safeguard can open an auto-fix PR that applies the least-privilege correction directly in your Terraform or CloudFormation source, so the fix lands in version control instead of as a one-off console change that drifts back open at the next deploy.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.