Skip to main content

S3 Account-Level Block Public Access

Overview

This check verifies that your AWS account has S3 Block Public Access settings enabled at the account level. These settings act as a safety net that prevents buckets from being accidentally made public, regardless of individual bucket settings.

Think of it as a master switch that says "no public access allowed" for your entire AWS account.

Risk

Without account-level public access blocking enabled, S3 buckets in your account could be made publicly accessible through ACLs (Access Control Lists) or bucket policies. This creates serious risks:

  • Data leaks: Sensitive files could be downloaded by anyone on the internet
  • Data tampering: Unauthorized users could modify or delete your files
  • Compliance violations: Publicly exposed data may violate regulations like HIPAA or GDPR
  • Malware hosting: Attackers could use your storage for malicious purposes

Remediation Steps

Prerequisites

You need permission to modify S3 account settings. Specifically, you need the s3:PutAccountPublicAccessBlock permission.

AWS Console Method

  1. Sign in to the AWS Management Console
  2. Go to S3 (search for "S3" in the search bar)
  3. In the left sidebar, click Block Public Access settings for this account
  4. 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
AWS CLI (optional)

Run the following command, replacing <account-id> with your 12-digit AWS account ID:

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

To find your account ID, run:

aws sts get-caller-identity --query Account --output text

You can combine these into a single command:

aws s3control put-public-access-block \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true \
--region us-east-1
CloudFormation (optional)

Note: AWS CloudFormation does not have a native resource type for S3 account-level public access block settings. You have two alternatives:

Option 1: Use a Custom Resource with Lambda

This approach uses a Lambda function to call the S3 Control API:

AWSTemplateFormatVersion: '2010-09-09'
Description: Enable S3 Account-Level Block Public Access using Custom Resource

Resources:
S3PublicAccessBlockLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: S3PublicAccessBlockPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:PutAccountPublicAccessBlock
- s3:GetAccountPublicAccessBlock
Resource: '*'

S3PublicAccessBlockLambda:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.12
Handler: index.handler
Role: !GetAtt S3PublicAccessBlockLambdaRole.Arn
Timeout: 60
Code:
ZipFile: |
import boto3
import cfnresponse

def handler(event, context):
try:
account_id = context.invoked_function_arn.split(':')[4]
s3control = boto3.client('s3control')

if event['RequestType'] in ['Create', 'Update']:
s3control.put_public_access_block(
AccountId=account_id,
PublicAccessBlockConfiguration={
'BlockPublicAcls': True,
'IgnorePublicAcls': True,
'BlockPublicPolicy': True,
'RestrictPublicBuckets': True
}
)

cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
except Exception as e:
print(f"Error: {e}")
cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})

S3PublicAccessBlockCustomResource:
Type: Custom::S3AccountPublicAccessBlock
Properties:
ServiceToken: !GetAtt S3PublicAccessBlockLambda.Arn

Option 2: Use AWS CLI in a deployment script

If you prefer not to use Custom Resources, run the AWS CLI command as a post-deployment step in your CI/CD pipeline.

Terraform (optional)

Terraform has native support for this setting:

terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

resource "aws_s3_account_public_access_block" "account_block" {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

Deploy with:

terraform init
terraform plan
terraform apply

Verification

After making changes, verify the settings are applied:

In the AWS Console:

  1. Go to S3 > Block Public Access settings for this account
  2. Confirm all four settings show as On
CLI verification
aws s3control get-public-access-block \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--region us-east-1

Expected output (all values should be true):

{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}

Additional Resources

Notes

  • This is a high-severity finding. Account-level public access blocking is considered a security best practice and should be enabled in all AWS accounts.
  • Existing public buckets: Enabling these settings will not automatically make existing public buckets private. Review individual buckets that require public access and ensure they are intentionally configured.
  • Legitimate public access: If you have buckets that genuinely need public access (e.g., static website hosting), you can configure exceptions at the bucket level while keeping account-level protection enabled. The bucket-level settings can override the "Block" settings but not the "Ignore" or "Restrict" settings.
  • CloudFormation limitation: Native CloudFormation support is not available; use the Custom Resource approach shown above or Terraform.