Talk to us
WhatsApp us

Free cloud cost review: we will find the waste in your AWS or Azure bill in 5 business days. Book it

Security & compliance

S3 bucket security: the controls that actually matter

Public S3 buckets remain one of the most reliable sources of data exposure. The controls are simple; applying them consistently is the hard part.

  • Updated
  • 3 min read

The short answer

The most important S3 control is Block Public Access, enabled at the account level so individual bucket settings cannot override it. Beyond that: encryption at rest, versioning with MFA delete for critical data, access logging, and bucket policies that grant specific actions to specific principals rather than using wildcards.

Key takeaways

  • Enable Block Public Access at account level, not per bucket
  • Versioning is the practical defence against ransomware and mistakes
  • Access logging is what makes an incident investigable
  • Use a service control policy so nobody can re-enable public access
S3 bucket security: the controls that actually matter — illustration

Part of our guide to Cloud security: the configuration is the attack surface.

Public S3 buckets have been behind a long run of publicised data exposures. The controls to prevent it are simple and free; the difficulty is applying them consistently across an estate where buckets get created by many teams over many years.

Block Public Access, at the account level

This is the control that matters most. Enabled at the account level, it overrides individual bucket ACLs and policies, so a team cannot accidentally expose a bucket even with a permissive policy.

Turn it on for every account. Where a bucket genuinely must serve public content — static assets, a public dataset — the better pattern is to keep the bucket private and put CloudFront in front of it with origin access control. That way public reach is an explicit, reviewable piece of architecture rather than a bucket setting.

Then add a service control policy preventing anyone disabling it. Otherwise you are relying on nobody ever deciding it is blocking their work.

Bucket policies

Grant specific actions to specific principals on specific resources. The patterns to avoid:

  • "Principal": "*" without a tight condition — this is what public means
  • "Action": "s3:*" where read access was intended, since it includes delete and policy modification
  • Resource wildcards spanning every bucket in the account

Prefer identity-based policies on roles for internal access, and reserve bucket policies for cross-account grants and service integrations where they are genuinely needed.

Encryption

Server-side encryption is on by default for new buckets. The decision is which key: provider-managed is simpler and appropriate for most data, while customer-managed keys give you control over rotation and an additional access-control layer through key policy.

Use customer-managed keys where regulation requires demonstrable control over the key lifecycle. Be deliberate, because a key policy that locks everyone out makes the data unrecoverable.

Versioning and deletion protection

Versioning keeps previous versions when an object is overwritten or deleted. It is the practical defence against both ransomware and ordinary human error, and it is the difference between an incident and an inconvenience.

For critical buckets add MFA delete, which requires multi-factor authentication to permanently remove a version. Pair versioning with lifecycle rules that expire old versions, or storage cost grows indefinitely.

Object Lock provides write-once-read-many semantics where retention must be provable — often a regulatory requirement rather than a security preference.

Logging

Enable access logging or CloudTrail data events for buckets holding anything sensitive. This is what makes an incident investigable: without object-level logging you cannot answer whether data was actually read, only that access was possible.

Data events carry a cost, so enable them for sensitive buckets rather than universally.

Finding what you already have

Audit the existing estate rather than only securing new buckets. IAM Access Analyzer for S3 identifies buckets accessible from outside the account. Combine that with a bucket inventory and check each one for public access settings, policy wildcards, encryption, versioning and logging.

Expect the audit to find buckets nobody remembers creating. Those are usually the ones worth looking at first.

Frequently asked questions

Keep the bucket private and put CloudFront in front of it using origin access control. Public reach becomes an explicit piece of architecture rather than a bucket setting somebody can toggle.

For anything you would miss, yes — it is the practical defence against both ransomware and human error. Pair it with lifecycle rules that expire old versions, otherwise storage grows indefinitely.

No, they carry a per-event cost. Enable them for buckets holding sensitive data, where being able to prove whether an object was actually read is worth paying for.

Keep reading