Skip to main content

S3 Bucket Public Access

Overview

This check verifies that your Amazon S3 buckets are not publicly accessible. It examines bucket ACLs (Access Control Lists), bucket policies, and Public Access Block settings to ensure your data is not exposed to the internet.

Risk

Severity: Critical

A publicly accessible S3 bucket can lead to:

  • Data breaches: Anyone on the internet can read your files
  • Data tampering: Attackers may modify or delete your data
  • Malware distribution: Your bucket could be used to host malicious content
  • Credential exposure: Secrets or API keys stored in files could be stolen and used for further attacks

Many high-profile data breaches have occurred due to misconfigured S3 buckets.

Remediation Steps

Prerequisites

You need permission to modify S3 bucket settings. Specifically, you need the s3:PutBucketPublicAccessBlock permission.

AWS Console Method

  1. Open the Amazon S3 console
  2. Click on the bucket name that failed the check
  3. Select the Permissions tab
  4. Under Block public access (bucket settings), click Edit
  5. Check all four boxes:
    • Block public access to buckets and objects granted through new access control lists (ACLs)
    • Block public access to buckets and objects granted through any access control lists (ACLs)
    • Block public access to buckets and objects granted through new public bucket or access point policies
    • Block public and cross-account access to buckets and objects through any public bucket or access point policies
  6. Click Save changes
  7. Type confirm in the confirmation dialog and click Confirm

Important: If your bucket intentionally hosts public content (like a static website), blocking public access will break that functionality. Consider using CloudFront with Origin Access Control instead.

AWS CLI Method

Block all public access for a specific 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"

Replace <your-bucket-name> with your actual bucket name.

To block public access at the account level (recommended - applies to all buckets):

aws s3control put-public-access-block \
--account-id <your-account-id> \
--region us-east-1 \
--public-access-block-configuration \
"BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
CloudFormation Template

Use this template to create a new S3 bucket with public access blocked:

AWSTemplateFormatVersion: '2010-09-09'
Description: S3 bucket with public access block enabled

Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket

Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true

Outputs:
BucketArn:
Description: ARN of the S3 bucket
Value: !GetAtt S3Bucket.Arn

Deploy with:

aws cloudformation deploy \
--template-file template.yaml \
--stack-name s3-secure-bucket \
--region us-east-1 \
--parameter-overrides BucketName=<your-bucket-name>
Terraform Configuration
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}

resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
}

resource "aws_s3_bucket_public_access_block" "this" {
bucket = aws_s3_bucket.this.id

block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

Apply with:

terraform apply -var="bucket_name=<your-bucket-name>"

Verification

After making changes, verify the fix worked:

  1. In the S3 console, go to your bucket's Permissions tab
  2. Under Block public access, all four settings should show On
  3. The Access column on the bucket list should show Bucket and objects not public
CLI Verification
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
}
}

Additional Resources

Notes

  • Account-level vs bucket-level: AWS recommends enabling Public Access Block at the account level. This provides a safety net even if individual bucket settings are misconfigured.

  • Existing public objects: Enabling these settings does not automatically remove existing public ACLs. It prevents them from granting public access while the block is in place.

  • Static website hosting: If you need to host a public static website, consider using CloudFront with Origin Access Control (OAC) instead of making your bucket public. This provides better security and performance.

  • Cross-account access: The RestrictPublicBuckets setting also blocks cross-account access granted through public bucket policies. If you have legitimate cross-account access needs, use bucket policies with specific account principals instead of public policies.