How to avoid (basic) S3 bucket policy security blunders

If you’re just starting out, S3 bucket policies can make you go:

If you are looking to understand the intricacies of S3 bucket policies and also avoid common cloud security blunders, allow me to be your guiding light!

What really is an S3 bucket policy?

An S3 bucket policy is a JSON file attached to an S3 bucket. You can view this under Bucket Policy under the Permissions when you select your S3 bucket. It essentially one of the main ways to control who or what can access the S3 objects you have stored in your S3 bucket.

Note: Bucket policies are limited to 20 KB in size!

What constitutes an S3 bucket policy JSON?

  • Version: Pertains to the version of the policy language and is not the version of YOUR policy. This element needs to match one of the documented values, the latest being “2012–10–07”.
    Note: Don’t change it, unless you have some extremely peculiar need to use a previous version. (which I highly suspect you would)

Note: Dont change it, unless you have some extremely peculiar need to use a previous version. (which I highly suspect you would)

  1. Statement: Is the main body of the policy. This is really where the magic happens, so you ought to plan this carefully. Each array in the Statement block contains:
  • Effect: Specifies whether you wish to allow a resource to be either allowed or denied access. Is either “Allow” or “Deny”

Note: “Deny” always trumps “Allow” i.e. even if a different policy allows access, the “Deny” action on it will trump that allowed access. Also, if you do not explicitly specify “Allow” to a resource, access is implicitly denied.

  • Resource: You would generally use an AWS ARN to identify a resource. Buckets, objects, access points, and jobs are the Amazon S3 resources for which you can allow/deny permissions. For more information, see Amazon S3 resources.
  • Action: For each resource, there are specific S3 related “actions” i.e. what you are allowed to do with the S3 object or bucket. For e.g. “s3:GetObject” if set to “Allow” in the “Effect” field, allows you to download or “get” your S3 object from the specified S3 bucket. For more information, see Amazon S3 actions.

Note: You can set specific actions for specific ARNs (recommended for enhanced security).

  • Principal: Specifies either an AWS account, AWS user or another AWS entity like an AWS service like “” or an IAM role. For more information, see Principals.

Note: It’s almost never recommended to use “*” in your Principal. This allows/denies literally ANY user on the internet to access your bucket, depending on your “Effect” field.

  • Condition: Conditions are similar to for example, an if condition loop, wherein you check for a particular is true or equals or something else. For e.g. You can put conditions to specify specific IP addresses from where your S3 bucket should be allowed accessed. You may very well wish to deny access from specific IP addresses as well. In that case, too, Conditions would come in handy. For more information, see Amazon S3 condition key examples.
  • Sid: statement-ID is an optional identifier that you provide for the policy statement. You can assign a Sid value to each statement in a statement array.

Common cloud security S3 bucket policy blunders:

  1. Setting public access on your S3 bucket

You have probably read the news about an embarrassing data leak by Accenture in 2017. There are other examples, where if you goof this part up, your company may actually endure massive financial losses and significant damage to its reputation, not to mention putting your own job and reputation in jeopardy.

But what does setting public access mean? Setting “*” in the Principal field along with “Allow” in the Effect field of your JSON policy. It literally allows ANY user on the internet to access your S3 bucket objects. In fact, here’s a little table I’ve made to simplify some do’s and don’ts for you:

AWS has also actually come up with a Blocking Public Access settings feature to avoid this blunder. Read more about it here!

2. Allowing more than necessary S3 actions to a particular AWS IAM entity

When it comes to cloud security, the rule really is to allow least privilege. Keeping it minimum although tedious, really is the safer road to take. This can be made easier, if you use the S3 bucket policy generator, at first, to understand the different S3 actions that come under read, write, permissions and tag management levels. As you get more advanced, however, knowing some of these actions will be beneficial when customizing policies.

3. Allowing more than necessary privileges to the AWS IAM entity that is accessing your S3 bucket

If you didn’t already know, CapitalOne had a massive security breach in 2019 because someone acquired, what is simply put, God-level access to an IAM role and copied data using that role to an S3 bucket outside of CapitalOne. 100M users were affected by this breach. This is just an example of how important it is to implement and maintain least IAM privileges on the IAM entitities (user, roles, groups, policies). But security threats don’t always come from the outside. Even providing access to more members than necessary in your own organization is creating a possibility for a breach.

Each IAM entity which has access to S3 buckets, should be restricted to a specific set of S3 buckets, the allowed S3 actions should be set to a minimum. It may not appear to be the most “fun” job, but I cannot emphasize the importance to err on the side of caution more.

To summarize: Keep only specific S3 actions, on restricted S3 buckets, to restricted IAM entities ONLY. This includes, IAM policies attached to roles, trust relationships in IAM roles, using groups to manage IAM roles/users appropriately etc.

4. Not enforcing encryption on your S3 objects at rest and in transit

So you managed to do things right in your bucket policy, it still makes sense to encrypt your S3 objects at rest. AWS provides options to use KMS keys or AES256 to encrypt your objects at rest.

You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic. Allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on Amazon S3 bucket policies. Use these options as necessary and often!

5. Not monitoring your S3 bucket and events happening on it

No matter how secure you make your buckets, you ought to spend time creating systems and/or utilizing the various options presented by AWS. There could be any number of AWS accounts and S3 buckets in a given organization, and keeping track of who does what and when, is nearly impossible, especially is the bucket is versioned. Oh the horror of keeping track of version and files overwrites (Shudder!)

The following table has 3 things I’d definitely recommend you do to get more insight into your S3 buckets:

I’d recommend this article by AWS for getting into even more details about securing S3 buckets!

If you want to know the basics of securing your S3 bucket, read my Medium blog here. Thanks for reading!

Rational thinking Engineer, with a scientist’s eye for detail | An old soul trapped in a millennial’s body | I write about what I know and how I feel.