Skip to content
AWS aws storage 5 min read

Blocking Public Access

Almost every famous “company leaks millions of records on an open S3 bucket” headline traces back to one mistake: a bucket that was accidentally made public. Amazon S3 (Simple Storage Service, AWS’s object storage) ships with a feature called Block Public Access (BPA) that exists to stop exactly this. It is a safety net that sits above your bucket policies and ACLs (Access Control Lists), and it can override anything that would expose your data. This page explains the four settings, how account scope and bucket scope interact, and the one rule that prevents almost all S3 leaks: leave it on.

What Block Public Access actually does

Block Public Access is not another permission rule that gets merged with your policies. It is a veto. Even if a bucket policy says "Principal": "*" with "Effect": "Allow" (meaning “anyone on the internet may read this”), BPA can simply refuse to honor it. Think of it as a master switch that says “I do not care what the policies say — do not let this become public.”

It works at two scopes:

ScopeSet onEffect
Account levelThe whole AWS account (per Region)Applies to every bucket in the account, current and future
Bucket levelOne individual bucketApplies only to that bucket

The two combine with a simple OR rule: if either the account or the bucket blocks something, it is blocked. A bucket can be more restrictive than the account, but it can never be less restrictive. So turning BPA on account-wide is a powerful guardrail — no individual bucket can quietly opt out and go public.

Since April 2023, AWS enables all four BPA settings by default on every new bucket, and ACLs are disabled by default too. This is a deliberate “secure by default” stance.

The four settings explained

BPA is made of four independent toggles. They split along two lines: ACLs vs policies, and block new vs ignore/restrict existing.

SettingWhat it controlsPlain-English meaning
BlockPublicAclsNew requestsReject any PUT request that tries to set a public ACL
IgnorePublicAclsExisting stateIgnore all public ACLs already on the bucket or its objects
BlockPublicPolicyNew requestsReject any bucket policy that would grant public access
RestrictPublicBucketsExisting stateIf the bucket is already public, limit access to AWS service principals and authorized users only

The first two deal with ACLs (the legacy 2006-era per-object permission system). The last two deal with bucket policies. The “Block” settings stop you from creating public access; the “Ignore”/“Restrict” settings neutralize public access that already exists. Enabling all four gives you the strongest protection, which is why that is the recommended default.

Gotcha: The overwhelming majority of S3 data leaks come from someone turning BPA off “just to test something” and then forgetting to turn it back on. Treat disabling BPA as a high-risk change that needs review, never a casual experiment.

When to use this (and when not to)

Use it: always, on every bucket. There is no normal scenario where a private bucket benefits from BPA being off. Logs, backups, application uploads, data lakes, build artifacts — all should keep BPA fully enabled.

The one exception is a bucket whose entire purpose is to serve public content directly (a legacy static website endpoint). Even then, the modern answer is not to disable BPA. Instead, keep the bucket private and serve it through Amazon CloudFront (AWS’s content delivery network) using Origin Access Control (OAC). CloudFront fetches objects from the private bucket on the viewer’s behalf, so the world can read your content while the bucket itself stays locked down. You get HTTPS, caching, and a custom domain for free.

ApproachBucket public?Recommended?
Make the bucket public via policyYesNo — last resort only
Keep BPA on, front with CloudFront + OACNoYes — the modern standard

There is no extra charge for OAC; you pay normal CloudFront request and data-transfer rates, which for public content are usually cheaper than serving directly from S3 anyway.

Checking and setting BPA

Via the console

  1. Open the S3 console and click your bucket name (for account-wide settings, choose Block Public Access settings for this account in the left sidebar instead).
  2. Go to the Permissions tab.
  3. Find Block public access (bucket settings) and choose Edit.
  4. Tick Block all public access (this selects all four) and choose Save changes.
  5. Type confirm in the dialog and confirm.

Via the AWS CLI

Check the current state of a bucket:

aws s3api get-public-access-block --bucket devcraftly-assets

Output:

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

Enable all four on a single bucket:

aws s3api put-public-access-block \
  --bucket devcraftly-assets \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

This command prints nothing on success.

Lock it down for the entire account (using your 12-digit account ID):

aws s3control put-public-access-block \
  --account-id 111122223333 \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

Tip: Set BPA at the account level once. After that, no engineer can accidentally make any bucket public, even with a wide-open bucket policy. This single setting prevents the most common cause of S3 breaches.

Enforcing it as code

If you manage buckets with CloudFormation, the BPA block is part of the bucket resource:

Resources:
  AssetsBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: devcraftly-assets
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        IgnorePublicAcls: true
        BlockPublicPolicy: true
        RestrictPublicBuckets: true

Defining it in your template means every deploy re-asserts the secure state, so a manual change in the console gets reverted on the next stack update.

What happens when BPA is on

If a public bucket policy is present but BPA blocks it, anonymous requests return 403 Access Denied, and the S3 console clearly labels the bucket as “Not public.” If your “public” objects unexpectedly return Access Denied, check BPA before you start debugging the policy — nine times out of ten, BPA is doing its job correctly.

Best Practices

  • Enable all four BPA settings at the account level so no bucket can ever go public by accident.
  • Keep BPA on for every individual bucket; never disable it “to test.”
  • Serve public content through CloudFront with Origin Access Control, keeping the bucket itself private.
  • Define BPA in CloudFormation or Terraform so the secure state is enforced on every deploy.
  • Use IAM Access Analyzer for S3 to get alerts the moment any bucket becomes publicly accessible.
  • Keep ACLs disabled (Object Ownership = Bucket owner enforced) so the ACL-related BPA settings have less to defend against.
  • Treat any request to turn off BPA as a reviewed, documented change — not a quick fix.
Last updated June 15, 2026
Was this helpful?