S3 Bucket Public List ACL
Overview
This check verifies that your S3 buckets are not publicly listable through Access Control Lists (ACLs). A bucket fails this check if its ACL grants READ, READ_ACP, or FULL_CONTROL permissions to "Everyone" (AllUsers) or "Any authenticated AWS user" (AuthenticatedUsers).
Risk
Severity: Critical
If your bucket is publicly listable, attackers can:
- Discover your data - See all object names, sizes, and last modified dates
- Map your bucket structure - Understand how you organize files for targeted attacks
- Find sensitive files - Locate backup files, configuration files, or data exports
- Modify access controls - With
FULL_CONTROL, attackers can change who has access
This is often the first step in a data breach involving S3 buckets.
Remediation Steps
Prerequisites
- Access to the AWS Console with permission to modify S3 bucket settings, OR
- AWS CLI configured with appropriate credentials
Required IAM permissions
You need the following permissions:
s3:GetBucketPublicAccessBlocks3:PutBucketPublicAccessBlocks3:GetBucketAcls3:PutBucketAcls3:GetBucketOwnershipControlss3:PutBucketOwnershipControls
AWS Console Method
- Open the Amazon S3 console
- Click on the bucket name that failed the check
- Select the Permissions tab
- Under Block public access (bucket settings), click Edit
- Check all four boxes:
- Block public access to buckets and objects granted through new ACLs
- Block public access to buckets and objects granted through any ACLs
- Block public access to buckets and objects granted through new public bucket or access point policies
- Block public access to buckets and objects granted through any public bucket or access point policies
- Click Save changes
- Type
confirmin the confirmation dialog and click Confirm
Recommended additional step: Disable ACLs entirely by setting Object Ownership to "Bucket owner enforced":
- On the same Permissions tab, find Object Ownership
- Click Edit
- Select ACLs disabled (recommended) / Bucket owner enforced
- Check the acknowledgment box
- Click Save changes
AWS CLI (optional)
Enable Block Public Access on the bucket:
aws s3api put-public-access-block \
--bucket <your-bucket-name> \
--region us-east-1 \
--public-access-block-configuration '{
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}'
Disable ACLs by setting Object Ownership to BucketOwnerEnforced:
aws s3api put-bucket-ownership-controls \
--bucket <your-bucket-name> \
--region us-east-1 \
--ownership-controls '{
"Rules": [{"ObjectOwnership": "BucketOwnerEnforced"}]
}'
Replace <your-bucket-name> with your actual bucket name.
CloudFormation (optional)
Use this template to create a new bucket with Block Public Access enabled and ACLs disabled:
AWSTemplateFormatVersion: '2010-09-09'
Description: S3 Bucket with Block Public Access enabled
Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket to secure
Resources:
S3BucketBlockPublicAccess:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
Outputs:
BucketName:
Description: Name of the secured S3 bucket
Value: !Ref S3BucketBlockPublicAccess
Note: CloudFormation cannot modify the Block Public Access settings of an existing bucket directly. For existing buckets, use AWS::S3::BucketPolicy or the AWS CLI.
Terraform (optional)
variable "bucket_name" {
description = "Name of the S3 bucket to secure"
type = string
}
resource "aws_s3_bucket" "secure_bucket" {
bucket = var.bucket_name
}
resource "aws_s3_bucket_public_access_block" "secure_bucket" {
bucket = aws_s3_bucket.secure_bucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_ownership_controls" "secure_bucket" {
bucket = aws_s3_bucket.secure_bucket.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}
For existing buckets, you can import them and apply the aws_s3_bucket_public_access_block resource:
terraform import aws_s3_bucket.secure_bucket <your-bucket-name>
Verification
After remediation, verify the fix:
- In the S3 console, open your bucket and go to the Permissions tab
- Confirm Block public access shows "On" for all four settings
- Confirm Object Ownership shows "Bucket owner enforced" (ACLs disabled)
CLI verification commands
Check Block Public Access settings:
aws s3api get-public-access-block \
--bucket <your-bucket-name> \
--region us-east-1
Expected output (all values should be true):
{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}
Check the bucket ACL:
aws s3api get-bucket-acl \
--bucket <your-bucket-name> \
--region us-east-1
The output should NOT contain grants to:
http://acs.amazonaws.com/groups/global/AllUsershttp://acs.amazonaws.com/groups/global/AuthenticatedUsers
Additional Resources
- Blocking public access to your Amazon S3 storage
- Controlling ownership of objects and disabling ACLs
- The meaning of "public" in Amazon S3
- Using Amazon S3 Block Public Access
Notes
-
Account-level vs bucket-level settings: AWS evaluates Block Public Access at both the account level and bucket level, using the most restrictive combination. Consider enabling Block Public Access at the account level for all buckets.
-
Existing public objects: Enabling "Ignore public ACLs" does not remove existing ACL grants; it simply ignores them. The ACLs remain but have no effect.
-
Applications relying on public access: Before enabling these settings, verify that no applications depend on public bucket listing. If public read access is needed, consider using CloudFront with Origin Access Control (OAC) or presigned URLs instead.
-
Directory buckets: Block Public Access is not supported for S3 Express One Zone directory buckets. They use IAM-based access control only.