Enforcing AWS S3 Read-Only Roles with Least Privilege

The bucket lay open, its contents exposed to anyone with the wrong set of permissions. In AWS S3, this is how data leaks start — not with a big breach, but with a subtle gap in policy enforcement.

To lock down read-only roles in AWS S3, you must control IAM policies with precision. A read-only role should give users the ability to list and get objects, but nothing else. The foundation is the s3:GetObject and s3:ListBucket actions. Every other action — especially s3:PutObject, s3:DeleteObject, and bucket policy edits — must be denied explicitly. A strict least-privilege approach avoids accidental write access.

Here is a minimal policy for an S3 read-only role:

{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Action": [
 "s3:GetObject",
 "s3:ListBucket"
 ],
 "Resource": [
 "arn:aws:s3:::my-bucket",
 "arn:aws:s3:::my-bucket/*"
 ]
 }
 ]
}

Attach this policy to an IAM role instead of a user. Use temporary credentials via AWS STS to reduce long-term exposure. Review trust policies to ensure only approved principals can assume the role.

Policy enforcement for AWS S3 read-only roles also means testing. Simulate access with the AWS CLI using the same credentials your role will use. Attempt write operations and confirm they fail with AccessDenied. Automate this check with CI/CD pipelines to keep permissions aligned over time.

For extra safety, combine IAM role restrictions with S3 bucket policies. Deny all s3:Put* and s3:Delete* actions at the bucket level. Even if an IAM policy is changed, the bucket policy will enforce read-only behavior.

Ignore convenience in favor of control. Audit permissions. Remove old roles. Block public access settings unless absolutely required. Every permission is an attack surface.

If you need to enforce policies for AWS S3 read-only roles without spending weeks in setup, try it live in minutes at hoop.dev.