AWS S3 Security: How to Harden Buckets and Stop Leaks

Harden Amazon S3 with Block Public Access, least privilege policies, KMS encryption, Object Lock and detection. A practical engineer checklist.
To secure an Amazon S3 bucket, keep S3 Block Public Access on, leave ACLs disabled and control access with IAM and bucket policies, enforce encryption in transit and at rest, turn on versioning plus Object Lock for data you cannot afford to lose, and monitor everything with CloudTrail data events and IAM Access Analyzer. Most publicized "S3 leaks" are not AWS failures, they are configuration mistakes on the customer side of the shared responsibility model.
This guide walks through the controls a cloud security engineer is expected to apply on day one, in the order you should apply them.
Why S3 misconfiguration is still a top cloud risk
S3 is simple to use, and that is exactly the problem. A single overly broad bucket policy, one wildcard principal, or one forgotten public access point can expose millions of objects with no exploit and no malware involved. Attackers do not need to break encryption when a bucket is readable by anyone with the URL.
AWS has hardened the defaults considerably. Since April 2023, all new buckets in every Region are created with S3 Block Public Access enabled and ACLs disabled, and since January 2023 all new object uploads are encrypted at rest by default with SSE-S3. Those defaults protect new buckets. They do nothing for buckets created before the change, for buckets someone deliberately opened, or for access granted through IAM policies rather than public settings.
Understanding where AWS responsibility ends and yours begins is the foundation here. If that boundary is not yet clear, read our breakdown of the cloud shared responsibility model across AWS, Azure and GCP first.
Layer 1: block public access and leave ACLs off
S3 Block Public Access is the guardrail that overrides everything else. It can be applied at the account level and at the bucket level, and the account level setting wins. Turning it on at the account level means that even if a developer writes a public bucket policy, the request is still denied.
The four settings are:
| Setting | What it stops |
|---|---|
| BlockPublicAcls | New ACLs that grant public access |
| IgnorePublicAcls | Existing public ACLs from taking effect |
| BlockPublicPolicy | New bucket policies that grant public access |
| RestrictPublicBuckets | Public and cross-account access through existing policies |
Turn on all four at the account level unless you have a genuine static website or public dataset use case, and in that case use CloudFront with an origin access control instead of a public bucket.
Leave ACLs disabled. AWS now recommends the Bucket owner enforced setting for object ownership, which switches ACLs off entirely and makes IAM policies and bucket policies the single source of truth for access. Two overlapping permission systems is one too many, and ACLs are the one that gets audited least.
Layer 2: write least privilege access policies
With ACLs off, access comes from three places: IAM identity policies, the bucket policy, and any access point policies. Apply the same least privilege discipline you would apply anywhere else in IAM, which we cover in depth in our guide to AWS IAM security best practices.
Practical rules that catch most real findings:
- Never use
"Principal": "*"in a bucket policy without a condition that scopes it, for exampleaws:PrincipalOrgIDoraws:SourceVpce. - Avoid
s3:*. Grant the specific actions the workload uses, typicallys3:GetObject,s3:PutObjectands3:ListBucket. - Remember that bucket-level actions such as
ListBucketneed the bucket ARN, while object actions need the ARN plus/*. Mixing these up is the most common cause of an over-permissive policy. - Add an explicit deny for unencrypted transport using
aws:SecureTransport: false, so plain HTTP requests are rejected. - Restrict access to a VPC endpoint with
aws:SourceVpcewhen the data never needs to leave your network.
Use a service control policy in AWS Organizations to prevent anyone from disabling Block Public Access, so the guardrail cannot be removed by an account admin.
Layer 3: encryption that matches your compliance requirement
Every bucket is encrypted at rest by default with SSE-S3, using AES-256. That satisfies a baseline requirement, but it gives you no control over the key.
| Option | Key control | When to use it |
|---|---|---|
| SSE-S3 | AWS managed, no customer visibility | Default baseline, non-sensitive data |
| SSE-KMS with an AWS managed key | Key policy managed by AWS | Light compliance needs, CloudTrail visibility on key use |
| SSE-KMS with a customer managed key | You define the key policy and rotation | Regulated data, separation of duties, cross-account control |
| DSSE-KMS | Two layers of KMS encryption | Requirements that mandate double encryption |
For regulated workloads, choose a customer managed KMS key. It gives you a second independent authorization check: a caller needs both S3 permissions and kms:Decrypt on the key, which is a genuinely useful defense when an IAM policy is too broad.
Enable S3 Bucket Keys when you use SSE-KMS. They cut KMS request traffic and can reduce KMS request costs substantially. One caveat to plan for: Bucket Keys use the bucket ARN as the encryption context rather than the object ARN, so if your IAM or KMS key policies condition on the object ARN, update them before enabling the feature.
Note that AWS has announced it will disable SSE-C by default for all new buckets and selected existing buckets in April 2026. If any workload still supplies its own encryption keys on upload, confirm your plan now rather than discovering it during an outage.
Layer 4: protect against deletion and ransomware
Access control stops the wrong people from reading data. It does not stop the right people from deleting it, and it does not stop an attacker who has valid credentials.
- Versioning keeps every version of an object, so an overwrite or delete leaves the previous version recoverable. Enable it on anything that matters.
- MFA delete requires a second factor before a version can be permanently deleted or versioning can be suspended. It is configured by the bucket owner using root credentials, which makes it operationally heavy, so reserve it for the highest value buckets.
- Object Lock enforces write once read many retention. Governance mode blocks deletion for most users but allows a privileged role to override. Compliance mode blocks deletion for everyone, including the account root user, for the entire retention period. Object Lock requires versioning, and once enabled on a bucket you cannot suspend versioning or turn Object Lock off.
- Replication to a separate account, ideally with different credentials and a different key, protects against account level compromise.
Compliance mode is the control auditors want to see for regulatory retention. It is also unforgiving, so test the retention period on non-production data before you apply it at scale.
Layer 5: detect what policy review misses
Configuration reviews find what you thought to look for. Detection finds the rest.
- IAM Access Analyzer for S3 continuously reports buckets that grant access to anyone on the internet or to accounts outside your organization, whether the grant came from a bucket policy, an access point policy or an ACL. Review the findings weekly and archive the ones that are intentional so the queue stays meaningful.
- CloudTrail data events log object-level operations such as
GetObject,PutObjectandDeleteObject. These are not logged by default and they carry a cost, so enable them selectively on sensitive buckets rather than everywhere. - S3 server access logs give request-level detail and are useful for forensics, though they are delivered on a best effort basis rather than in real time.
- Amazon Macie discovers and classifies sensitive data such as credentials and personal information in your buckets, which answers the question policy review cannot: what is actually stored in there.
- AWS Config rules detect drift, for example a bucket where Block Public Access was disabled or default encryption was removed.
Alert on the changes, not just the state. A bucket policy modification on a production data bucket should generate a notification the same day, not appear in a quarterly report.
A practical hardening checklist
Work through this on every account you own:
- Enable Block Public Access at the account level, all four settings.
- Add a service control policy preventing anyone from turning it off.
- Set object ownership to Bucket owner enforced so ACLs stay disabled.
- Audit bucket policies for wildcard principals and
s3:*actions. - Add a deny statement for
aws:SecureTransport: falseon every bucket. - Move sensitive buckets to SSE-KMS with a customer managed key and enable Bucket Keys.
- Turn on versioning everywhere, and Object Lock where retention is required.
- Enable IAM Access Analyzer and triage findings on a schedule.
- Enable CloudTrail data events on sensitive buckets.
- Run Macie to find out what sensitive data you are actually storing.
Nothing on that list is exotic. The gap between a secure S3 estate and a leaked one is almost always discipline and repetition rather than advanced technique.
Frequently asked questions
Are new S3 buckets public by default? No. Since April 2023, all new S3 buckets in all AWS Regions have S3 Block Public Access enabled and ACLs disabled by default. A bucket only becomes public if someone deliberately changes those settings.
Is S3 data encrypted at rest automatically? Yes. All new object uploads to Amazon S3 are automatically encrypted with server-side encryption using S3 managed keys, known as SSE-S3, at no additional cost. You can upgrade a bucket to SSE-KMS if you need control over the key.
What is the difference between S3 Object Lock governance mode and compliance mode? In governance mode, users with special permissions can override the lock and delete or alter the object. In compliance mode, no user can overwrite or delete the object version for the retention period, including the account root user, and the retention period cannot be shortened.
Do I need MFA delete if I already have versioning? Not always. Versioning alone lets you recover from accidental overwrites and deletes. MFA delete adds protection against a permanent version delete by someone with valid credentials, so it suits high value buckets where the operational overhead is justified.
Does CloudTrail log every S3 operation by default? No. CloudTrail logs management events such as bucket creation by default, but object-level operations like GetObject and PutObject are data events and must be enabled explicitly on a trail.
Do I need to know S3 security to work as a cloud security engineer? Yes. Storage security is one of the most common interview topics and one of the most common real world findings, so expect to explain Block Public Access, bucket policies, KMS encryption choices and Object Lock in practical terms.
Put this into practice
Reading about bucket policies is not the same as writing one, breaking it, and fixing it. PrimeSec Academy's 20-week Cloud and AI Platform Security Engineer program puts you in a real AWS environment where you harden storage, build detection, and defend your decisions in a capstone review. See what you will build in the curriculum and the hands-on projects, or enroll when you are ready to start.
Further reading from AWS: Security best practices for Amazon S3 and Blocking public access to your Amazon S3 storage.
