S3 Access Denied From Block Public Access: Which Setting?

Logeshwaran
—

When Amazon S3 returns AccessDenied as you save a public policy or open an object anonymously, first check the four S3 Block Public Access settings at both bucket and account level. BlockPublicPolicy rejects a new public bucket policy, while RestrictPublicBuckets can stop public reads even when a public policy already exists. The counterintuitive part: turning off Block Public Access does not itself grant access—it only removes a guardrail, and you still need a valid allow policy. For most websites, keep the bucket private and use CloudFront Origin Access Control instead.

⚡ Quick Answer

• Inspect S3 → bucket → Permissions → Block public access (bucket settings), then the account settings and organization controls.

• CLI: aws s3api get-public-access-block --bucket BUCKET and aws s3control get-public-access-block --account-id ACCOUNT_ID.

• A failed public PutBucketPolicy usually points toward BlockPublicPolicy; a stored public policy whose reads fail points toward RestrictPublicBuckets, explicit denies, or another access control.

• Prefer private S3 plus CloudFront OAC unless your use case truly needs a directly public S3 endpoint.

Jake runs a phone-repair shop and wants to publish repair instructions. He considers storing the PDF files in a public S3 prefix, but his first attempt to save the bucket policy returns Access Denied. A small mistake here can expose customer photos stored alongside the manuals, so the safest answer matters more than making a red error disappear.

Jake can solve the problem without making the entire account public. The right sequence is to identify the precise control, choose an appropriate delivery architecture, and limit any deliberate public permissions to objects meant for everyone. The article follows that sequence, including the case where central security rules deliberately prohibit public access altogether.

Start with the exact operation that failed

If you are staring at a generic AccessDenied response, identify whether you were saving a bucket policy, uploading with an ACL, or requesting an object as an anonymous visitor. Those are different operations with different access evaluations. A single HTTP 403 status cannot by itself identify which one of the four public-access controls caused the problem.

A failed PutBucketPolicy request that introduces public permissions is especially suggestive of BlockPublicPolicy. An object that once loaded anonymously but no longer loads can be affected by RestrictPublicBuckets or IgnorePublicAcls, depending on the permission mechanism. Explicit denies, missing allows, and organization policies are other possible causes.

The S3 console can display an error when you attempt to save a bucket policy, and the CLI commonly reports AccessDenied for the corresponding operation. The response is not guaranteed to mention the Block Public Access flag by name. Check the settings rather than treating the wording as a complete diagnosis.

The action name in a CloudTrail management event can help you tell a failed policy write from a failed object request. The bucket and account settings then tell you whether the proposed permission would be suppressed or rejected. Remember to inspect the effective identity permissions of the person changing the configuration as well.

Understand the four settings without confusing them

If all four checkboxes look like variations of the same protection, distinguish whether each one targets ACLs or policies and whether it blocks a write or ignores permissions during access. ACL stands for access control list, an older way of granting access to individual buckets or objects. Bucket policies are JSON documents that specify who can perform particular actions on particular resources.

BlockPublicAcls rejects requests that attempt to add a public ACL. IgnorePublicAcls leaves public ACLs stored but does not honor the public grants they contain. They are not interchangeable: one stops a change from being accepted, while the other stops an accepted ACL from making data public.

BlockPublicPolicy rejects new bucket-policy updates that S3 recognizes as public. RestrictPublicBuckets changes the effective access to a bucket already using a public policy, restricting it to authorized principals in the owner account and AWS service principals. It can also block cross-account access that appears otherwise explicitly allowed in a public bucket policy.

These controls leave existing policies and ACLs in place; they are not a cleanup operation. If you disable one later, a previously stored public grant can become effective again. That makes reading the current policy and ACLs a necessary part of any change review.

Setting Rejects or ignores Why you notice it
BlockPublicAcls Rejects newly public ACL writes Upload or ACL update fails
IgnorePublicAcls Ignores public ACL permissions Anonymous read fails despite old ACL
BlockPublicPolicy Rejects a newly submitted public policy Save policy fails
RestrictPublicBuckets Restricts access under a public policy Previously public reads and some cross-account access fail

Find which level wins: organization, account, or bucket

If you switch off a bucket checkbox and the policy still cannot be saved, check account-wide settings before trying another change. S3 evaluates the most restrictive applicable public-access configuration. A restrictive account setting cannot be overridden by the same flag being false on an individual bucket.

Organizations can centrally manage public-access restrictions as well. Where an organization policy applies, a local account administrator might be unable to change the relevant account settings. The correct response is to request an approved architectural exception or use a private distribution pattern, not repeatedly edit the bucket.

Bucket and account settings have distinct CLI endpoints. Use s3api get-public-access-block for a bucket and s3control get-public-access-block for an account. A bucket lookup returning a missing-configuration error does not prove that public access is permitted because a higher-level setting may still block it.

One successful setting change says nothing about other Regions, accounts, or resources. Check the identity and account ID printed by aws sts get-caller-identity, confirm the bucket owner, and capture the effective settings before troubleshooting further. This prevents you from making a sensitive change in a different account than the one serving traffic.

Jake: "I unchecked the bucket box. Why does the website still say Access Denied?"

Ethan: "An account or organization rule can still be tighter. The bucket switch cannot override the wider guardrail."

aws sts get-caller-identity
aws s3api get-public-access-block --bucket example-company-site-assets
aws s3control get-public-access-block --account-id 123456789012

Read failures caused by BlockPublicAcls

If an upload with --acl public-read fails while uploading without that flag works, inspect BlockPublicAcls. This setting rejects requests attempting to introduce public ACLs. A request can fail even if the caller has the normal s3:PutObject authorization, because the requested ACL is not permitted.

When Object Ownership is set to Bucket owner enforced, ACLs are disabled for that bucket. That newer ownership model can independently produce an AccessControlListNotSupported error for requests trying to set unsupported ACLs. Changing Block Public Access does not reverse Bucket owner enforced object ownership.

For current application design, prefer bucket policies and IAM over public ACLs. If an uploader still sets public-read out of habit, remove that parameter before making security settings weaker. The server-side ownership and policy model will then determine actual access.

An existing public ACL is not deleted when BlockPublicAcls is enabled. It is better to inventory and remove unwanted public ACLs than rely on a particular setting remaining enabled forever. That also reduces surprises during account migration or administrative changes.

aws s3api put-object --bucket example-company-site-assets --key public/logo.png --body logo.png --acl public-read
# If public ACLs are blocked, remove the ACL argument instead:
aws s3api put-object --bucket example-company-site-assets --key public/logo.png --body logo.png

Understand why IgnorePublicAcls can produce a 403

If you can inspect an object and see a historically public ACL but anonymous visitors receive Access Denied, check IgnorePublicAcls. This flag does not need to reject the upload or ACL-setting request to keep the object private. It simply prevents S3 from honoring the public portions of the ACL.

This matters for a migration from legacy ACL-based hosting to bucket policies. A team may claim that an object is public because a tool says public-read was set years ago. The effective permission can still be private, because newer controls take priority.

When you inspect ACLs through S3 APIs, be aware that effective permissions may be presented rather than the raw historical grants under some Block Public Access configurations. Use the full policy context and settings to interpret a 403. An ACL alone is not a reliable public-access test.

The durable fix is to pick a clear access strategy. For private downloads, use IAM, presigned URLs, or CloudFront; for intentional direct-public objects, use a tightly scoped bucket policy under an approved configuration. Mixing public ACLs and policies is harder to maintain and audit.

Diagnose BlockPublicPolicy when saving Principal star

If the console rejects a bucket policy containing "Principal": "*", BlockPublicPolicy is a likely cause when that statement gives unrestricted public access. That setting evaluates whether the submitted policy grants public access. It does not merely search the JSON text for an asterisk.

A wildcard principal with carefully constrained fixed conditions can sometimes be classified as nonpublic under S3 policy evaluation rules. Conversely, a policy can be judged public because of broad resource or condition patterns even when its author believes it is limited. The policy as a whole matters.

An explicit error returned by PutBucketPolicy may simply be AccessDenied; separate IAM authorization failures can look similar. First ensure you have s3:PutBucketPolicy in the correct account. Then inspect the public-policy block flag at the bucket and account levels.

A deliberate public policy requires organizational approval and a clear resource scope. If the only purpose is to distribute a website through CloudFront, leave BlockPublicPolicy enabled and grant the CloudFront service principal a narrowly scoped private read instead. That avoids a public S3 origin entirely.

aws s3api put-bucket-policy --bucket example-company-site-assets --policy file://public-prefix-policy.json
# Representative response:
# An error occurred (AccessDenied) when calling the PutBucketPolicy operation: Access Denied

Explain RestrictPublicBuckets on an existing public policy

If a bucket policy was accepted earlier but anonymous requests now return Access Denied, inspect RestrictPublicBuckets. Its purpose is not to delete a public policy; it limits who can actually access a bucket with one. The effect can be surprising after a security team adds account-level guardrails.

The control also affects cross-account delegation within a bucket policy considered public. A specific partner account might be named in one statement, but the presence of a separate public statement can cause restrictions to apply more broadly. Treat that interaction as a reason to simplify the bucket policy and separate public from private workloads.

Authorized identities in the bucket owner account can continue to operate subject to their permissions. Public viewers cannot rely on the blocked policy, and an ordinary cross-account caller may be blocked even when its own role has an allow. That is why an administrator test and an anonymous browser test can return different outcomes.

If your use case needs partners rather than the world, remove the public grants and write targeted cross-account permissions. If the use case needs unauthenticated download access, consider CloudFront OAC as a cleaner delivery boundary. You should not disable a broad safety control to repair a policy that does more than the application requires.

Jake: "The policy still says everyone can read the file. Why can nobody open it?"

Ethan: "The policy was not deleted, but the restriction blocks public access when S3 evaluates the request."

Understand what S3 calls a public policy

If you think your policy is private because it mentions a network condition, examine the condition values carefully. S3 begins from the assumption that a bucket policy is public and determines whether permissions are restricted by supported fixed values. Some conditions can establish constrained access; arbitrary wildcards and variables often cannot.

A narrowly specified aws:SourceVpce endpoint or aws:SourceVpc value can help bound a policy, depending on how the condition is written. Fixed aws:SourceAccount and aws:SourceArn values also matter for supported use cases. An unrestricted wildcard for everyone is the clearest intentionally public form.

A CIDR-based aws:SourceIp policy must be evaluated for how broad its permitted network is. Broad address ranges can still be classified public even when the document contains an IP condition. Adding just any condition is no guarantee that a public policy becomes nonpublic.

To reason about the evaluation, identify the principal, action, resource, and conditions in each allow statement. Check whether the policy exposes any object, even if only one prefix is affected. A policy that lets everyone read public/* is still a public policy and is intentionally blocked by BlockPublicPolicy.

Statement shape How to interpret Better next step
Principal: "*" with broad read Usually public Use only for intentional direct-public content
Specific CloudFront service principal and distribution condition Service access, not anonymous public Keep BPA on
Specific partner account role Targeted cross-account grant Avoid broad public statements alongside it
Broad IP or wildcard condition May still be public Use supported fixed restrictive conditions

Match exact-looking errors to the operation

If you see An error occurred (AccessDenied) when calling the PutBucketPolicy operation: Access Denied, that establishes that the policy-write request was denied. It does not by itself prove which permission system did so. Missing IAM authorization, bucket ownership, or public-policy blocking can all be part of the investigation.

For public ACL attempts, failures may also appear as AccessDenied on PutObjectAcl, PutBucketAcl, or an upload operation. For ACL-disabled buckets, AccessControlListNotSupported is a separate and more specific diagnosis. Check whether the application still sends an ACL header before changing Block Public Access.

For anonymous object reads, an HTTP 403 with AccessDenied can be consistent with several controls, including policy restrictions and missing permission. A signed IAM request can also fail for explicit denies or other policies unrelated to public access. Compare one request made with the intended identity and one truly anonymous request to isolate the issue.

A policy rejected by Block Public Access is not stored as the new bucket policy. A stored policy blocked at evaluation time remains present, so looking only at the bucket policy JSON is not enough. The table below maps the symptom to your next diagnostic action.

Observed error Likely branch to inspect Important alternative
403 on PutBucketPolicy BlockPublicPolicy Missing s3:PutBucketPolicy
403 on ACL-setting operation BlockPublicAcls Other IAM deny
AccessControlListNotSupported ACLs disabled by Object Ownership Remove ACL header
403 on anonymous GetObject RestrictPublicBuckets, IgnorePublicAcls No public allow or explicit deny

Use the console without opening unrelated buckets

If you are troubleshooting one website bucket, begin with its Permissions tab instead of opening account-wide protections. Navigate to S3, select General purpose buckets, choose the bucket, and inspect Block public access (bucket settings). Record the four current values and review the bucket policy beneath them.

Next inspect the account-level Block Public Access controls from the S3 account settings area. If the account is governed through AWS Organizations, determine whether a central policy prevents changes. Make the change at the narrowest permitted scope and only after deciding whether anonymous access is genuinely required.

An administrator may have permission to edit a bucket policy but lack permission to edit Block Public Access settings. This separation is intentional in controlled environments. If the console refuses a setting change, investigate IAM and organization governance rather than repeating the same action.

For a private CloudFront origin you can keep all four settings enabled. For direct anonymous access through a bucket policy, public-policy blocking and public-bucket restriction must not be effective at a higher level. Keep ACL-related protections enabled when you are not using ACLs.

  1. Open Amazon S3 and choose the intended general purpose bucket.
  2. Open Permissions and inspect Block public access (bucket settings).
  3. Review Bucket policy and Object Ownership separately.
  4. Check account-level public-access settings and any organization controls.
  5. Decide whether private CloudFront delivery meets the need.
  6. Make only an approved scoped change, then test both public and private objects.

Inspect and modify one bucket with the AWS CLI

If you prefer the command line, first verify which AWS account your active credentials belong to. The CLI does not infer the bucket owner from your intended environment. Use an explicit profile when several accounts are configured.

Inspect the bucket configuration with aws s3api get-public-access-block --bucket BUCKET. Then inspect account-wide settings with aws s3control get-public-access-block --account-id ACCOUNT_ID. Those operations are distinct and neither output should be treated as a substitute for the other.

When a direct-public policy is approved and higher-level protection permits it, set only the two policy-related flags to false for that bucket while leaving the ACL flags true. This is a deliberate exception, not the default recommendation. Record the old configuration so a later rollback is straightforward.

After changing the setting, read it back, apply the carefully scoped policy, and test an explicitly intended public object. Also test an object outside the allowed prefix to confirm it remains inaccessible anonymously. If a higher-level setting is still enabled, a bucket-level false cannot override it.

aws sts get-caller-identity
aws s3api get-public-access-block --bucket example-company-site-assets
aws s3control get-public-access-block --account-id 123456789012

# Approved direct-public bucket exception ONLY; no higher-level blocks:
aws s3api put-public-access-block \
  --bucket example-company-site-assets \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=false,RestrictPublicBuckets=false

This command sets the entire four-field bucket configuration, not merely the two fields set to false. Before running it, compare the current values and any local governance requirements. A change to false does not itself publish any object.

Worked example: expose only a static-site prefix

If your requirement really is a direct S3 public-read location, imagine a bucket named example-company-site-assets with public/index.html and private/customer-record.csv. Your goal is to allow anonymous GetObject only under the public prefix. There is no reason to grant public listing, uploading, deleting, or reading outside that prefix.

First verify the account and organization allow an exception; otherwise use CloudFront OAC and leave all public-access blocks enabled. Assuming the exception is permitted, retain both ACL controls and disable only the two policy controls for that bucket. Then apply the policy shown below using a local JSON file.

The public principal is deliberate in this example, so S3 treats the submitted document as a public policy. This exception still needs ordinary IAM authorization to write the policy, and organization-level restrictions can prevent it. The JSON resource ARN targets objects starting with public/, not the entire bucket.

Afterward, request the public HTML object without credentials and confirm the result is the expected content. Try an anonymous request for the private CSV and confirm it is not exposed. A 403 on the private object is the desired result, whereas a 403 on the public object means there is still an access condition to investigate.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadOnlyApprovedPublicPrefix",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-company-site-assets/public/*"
    }
  ]
}
aws s3api put-bucket-policy \
 --bucket example-company-site-assets \
 --policy file://public-prefix-policy.json

curl -I https://example-company-site-assets.s3.us-east-1.amazonaws.com/public/index.html
curl -I https://example-company-site-assets.s3.us-east-1.amazonaws.com/private/customer-record.csv

In this illustrative test, the public request is expected to return success when the file exists and all required permissions permit it, while the private request should not return its content anonymously. The exact HTTP response for the private key can depend on other permissions. Use a harmless marker object as your public test fixture, not an actual customer record.

Keep S3 private while serving a public website with CloudFront OAC

If you need internet users to download public files, an S3 bucket that grants access to anonymous callers is only one of your options. CloudFront Origin Access Control, or OAC, lets CloudFront send signed requests to a private S3 bucket. Your visitors fetch content through CloudFront, while the S3 origin remains protected.

Configure an S3 bucket origin using the regional S3 endpoint rather than treating an S3 website endpoint as an OAC-compatible S3 origin. Create an OAC that signs origin requests, and grant the CloudFront service principal s3:GetObject for the approved resources with a condition tied to your distribution ARN. A private bucket policy like that is not an anonymous Principal: "*" grant.

You can leave all four S3 Block Public Access settings on. This is especially valuable when you want HTTPS, caching, and a clear separation between the content delivery edge and storage permissions. It also avoids making every uploaded object eligible for public delivery through an S3 endpoint.

If you use S3 static website hosting specifically, note that its website endpoint behaves differently from a normal S3 origin and is treated as a custom origin in CloudFront. The OAC S3-origin pattern uses the REST-style S3 origin. Choose the architecture before editing policies, so you are not combining incompatible configurations.

{
 "Version": "2012-10-17",
 "Statement": [{
  "Sid": "AllowOnlyMyCloudFrontDistribution",
  "Effect": "Allow",
  "Principal": {"Service": "cloudfront.amazonaws.com"},
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::example-company-site-assets/public/*",
  "Condition": {"StringEquals": {
   "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E123EXAMPLE"
  }}
 }]
}

Jake: "If CloudFront serves my instructions to anyone, is my bucket public anyway?"

Ethan: "The files can be public through CloudFront while S3 itself accepts only authorized CloudFront origin requests. That is the useful separation."

Explain why presigned URLs work with Block Public Access enabled

If you need one customer to download a private invoice, a presigned URL is usually more appropriate than public bucket access. A presigned URL is a time-limited, signed request using the permissions of its creator. It does not need a bucket policy granting access to anonymous principals.

The signer must have permission to access the object, and ordinary denies still apply. That includes relevant bucket, IAM, encryption-key, and organization controls. Public-access blocking and a legitimate signed private download solve different problems.

Keep all four protections enabled while using presigned URLs. The customer receives a URL rather than AWS credentials, and the signed request authenticates access within its valid lifetime. This is easier to audit than allowing everyone on the internet to retrieve arbitrary private records.

If a presigned request fails, inspect expiration, signing credentials, object key, and authorization. Turning off public-access blocking is not the standard fix. The URL needs valid signed access, not a broad public ACL or bucket policy.

Jake: "A presigned link still works with all four boxes enabled?"

Ethan: "Yes, when its signer has the needed access and no other rule denies it. A signed private request is not the same as anonymous public access."

Understand the April 2023 defaults and ACL changes

If a tutorial created before 2023 instructs you to add public-read to every upload, it may not match new S3 buckets. Since April 2023, Amazon S3 has automatically enabled Block Public Access and disabled ACLs for new general purpose buckets by default. These defaults changed the starting point for new applications.

The ownership setting is Bucket owner enforced, which disables ACL-based permission management. An upload that supplies a public ACL can fail independently of the public-policy settings. Modern examples should use IAM and bucket policies, with CloudFront for public delivery when possible.

Existing buckets can have a different history, so their configuration should be inspected rather than inferred from the creation date alone. A legacy bucket might still contain public ACLs or a public bucket policy that was valid under older choices. Public-access blocks can prevent those older permissions from becoming effective.

This is why copying a tutorial verbatim can produce a failure that looks like a missing permission. The appropriate fix may be to remove ACL flags or redesign the application rather than weaken an account-wide guardrail. Read the actual bucket ownership and public-access settings before applying advice.

Bucket model Default direction What breaks old tutorials
New buckets since April 2023 Block Public Access enabled; ACLs disabled public-read ACL uploads
Older buckets Inspect individual configuration Legacy ACLs or public bucket policies may persist
Private CloudFront OAC origin Public blocks can stay enabled Must grant the CloudFront service principal

Find public buckets throughout your account

If you manage many buckets, manually opening every Permissions tab is not a dependable audit plan. IAM Access Analyzer for S3 can show external-access findings for buckets that allow public or cross-account access. Its findings also identify the permission mechanism involved.

In the S3 console, expand External access summary under General purpose buckets to review public-access findings. For this capability, you need an account-level external access analyzer for each Region being analyzed. Look at public findings separately from cross-account findings so partner sharing is not mistaken for internet exposure.

An Access Analyzer finding is not necessarily an instantaneous reflection of the latest change. Bucket-policy updates can take time to appear in findings, and account-level Block Public Access changes can take several hours to be reflected. For an urgent security assessment, also inspect current policy and setting values directly.

For continuous governance, combine Access Analyzer with appropriate AWS Config or Security Hub controls. Those services can flag unwanted public-read or public-write configurations across your environment. Their findings should trigger review rather than automatic blanket changes to approved public content.

  1. Open IAM Access Analyzer and ensure an external access analyzer exists for every Region you need to review.
  2. In S3, open General purpose buckets and expand External access summary.
  3. Open public-access findings and inspect how each bucket is shared.
  4. Export findings where appropriate and compare them with current bucket and account settings.
  5. Document intended exceptions and prioritize unintended public write access for urgent remediation.

Avoid breaking legitimate cross-account sharing

If a partner account suddenly loses access after a public-access policy change, inspect whether your bucket policy is classified as public. RestrictPublicBuckets can suppress cross-account access on a bucket with a public policy, including statements that appear to target a specific account. This catches teams that mixed partner access with anonymous access in the same policy.

The least risky design is to separate public content from partner-only resources. Use explicit account or role principals for partner sharing and keep that bucket policy nonpublic. The partner still needs appropriate authorization on its side and must meet any encryption requirements.

You should not change the account-wide policy simply to make one partner role work. First determine whether a broad public statement is creating the classification and restriction. Removing that statement can restore the intended nonpublic access design without a public bucket exception.

CloudTrail events and S3 authorization errors help distinguish the request type, but they complement a policy review rather than replacing it. Record the partner principal, requested object, and effective resource policy before proposing a change. This allows the security owner to approve a narrow cross-account grant.

Separate Block Public Access from other AccessDenied causes

If every Block Public Access flag is compatible with your intended request, the cause lies elsewhere, not in an S3 malfunction. A bucket policy can explicitly deny a principal, require a specific VPC endpoint, or limit requests by other conditions. IAM identity policies, service control policies, and ownership can also affect the result.

Encryption creates another branch. If a private object uses a customer managed AWS KMS key, the caller may require KMS permissions as well as S3 permissions. Turning off Block Public Access will not repair a missing kms:Decrypt authorization.

An object may not exist at the exact key the caller requested. Depending on the caller and its permissions, S3 can return Access Denied rather than revealing whether a key exists. Confirm the spelling, path, encoding, and version before diagnosing a public-access configuration.

Use the smallest test that isolates the failure: query the bucket public-access block, inspect the policy, and perform one signed and one unsigned read when appropriate. Record the HTTP operation and error message. A disciplined investigation is safer than disabling protections until the test passes.

Other reason for 403 What to inspect Why BPA changes will not solve it
Explicit IAM or bucket-policy deny Principal, conditions, service control Explicit deny takes priority
KMS key authorization Caller and key policies Different service authorization
Wrong object key Exact case and path No valid object to return
Wrong AWS account sts get-caller-identity Settings inspected on wrong resource

Restore protections and prevent a lingering public exception

If you created a bucket-level public exception for a temporary static site, define when it should end. Public access can remain live long after the project owner forgets about it. That matters when future uploads land beneath the permitted prefix without the original review.

Before turning restrictive flags back on, determine whether doing so will interrupt a legitimate public endpoint. Then remove the unneeded public grant and re-enable the policy block and restriction flags as appropriate. A planned transition to CloudFront OAC allows you to keep content available without a direct-public S3 policy.

Because Block Public Access does not delete an existing policy, simply turning on the blocks is a protective overlay rather than a full cleanup. Remove or narrow the policy itself as part of the rollback. That prevents the old grant from becoming active if someone later changes a flag.

Keep an approval record, the bucket name, the exact public prefix, and a confirmation that unrelated objects remain private. For a high-risk environment, add periodic findings review and automated configuration controls. Schedule a review after every application release that changes prefixes, ownership, or deployment roles, and retain the last approved policy for comparison. The ideal outcome is a public content path that cannot accidentally expand into customer data.

What to collect when nothing works

If a public-policy change still fails after you have inspected bucket, account, and organization settings, collect the exact operation name and full error message. Add your AWS account ID, bucket name, Region, current settings, and a sanitized policy. This gives support and your internal security team enough context to distinguish ownership, IAM, and public-policy restrictions.

If the console and CLI behave differently, run aws sts get-caller-identity in the CLI and compare its identity with the account and role selected in the console. Different credentials are a common explanation. Also check whether you are editing a bucket that belongs to another account.

A useful support question asks which effective access control denied one specific request, rather than demanding that every block be turned off. Include a request ID and timestamp when available. Keep customer data and credentials out of the case description.

If an organization-level control is the barrier, AWS Support cannot simply replace your organization administrator approval process. Coordinate with the policy owner and consider a private CloudFront origin architecture that meets the original business goal. A sound solution respects the boundaries that were put in place intentionally.

For a support case, you can use the following concise request while replacing the placeholders with real non-sensitive values. It asks for an effective-deny explanation and explicitly avoids a blanket public-access change. Include the timestamp and request ID only when you have them.

Subject: S3 PutBucketPolicy AccessDenied — identify effective public access restriction

Account: 123456789012
Bucket: example-company-site-assets
Operation: PutBucketPolicy
UTC time / request ID: [details]
Current bucket-level BPA: [four values]
Account or organization BPA: [known values]
Intent: anonymous GetObject only for public/*; all other keys remain private
Please identify the denying policy or public-access setting and confirm the narrowest supported resolution. No broad account-level public access is requested.

Choose the safe fix from the request you are actually making

If you are fixing a public-read failure during an incident, write down the business requirement before you touch the settings. Does the customer need a published website, a one-time private download, or access from a partner AWS account? Each of these needs a different permission boundary, and each can be solved without changing all four public-access flags. A clear requirement also makes your change easy for someone else to review after the service is restored.

For a published website, start by checking whether CloudFront is already in front of S3. If the site uses a CloudFront distribution configured with OAC, inspect the origin domain and the distribution ARN condition in the bucket policy. The browser should request the CloudFront hostname, not the private S3 object URL, because the latter is intentionally protected from anonymous callers. When you get Access Denied from CloudFront, compare the origin response and CloudFront configuration before declaring the S3 bucket publicly inaccessible by mistake.

For a one-time download, ask whether your service can generate a presigned link under an authorized IAM role. The link is not a request to turn the bucket public; it is an authenticated request with a limited lifetime. This avoids accidentally exposing every file with a matching file extension or common prefix, and it lets you keep account-wide protections intact. Check that the signing role has read permission and that any encryption-key conditions permit the operation, because public-access settings cannot compensate for missing private authorization.

For an external AWS partner, use the partner account or specific role ARN as the principal. Keep the bucket policy free of a separate anonymous read statement where possible, particularly if RestrictPublicBuckets is enabled. Ask the partner to check its IAM identity-side authorization as well, because a resource-policy grant is not always the only decision involved. Document the precise objects, required actions, and retention period so the shared resource does not become a permanent exception without an owner.

For an approved directly public download prefix, keep uploads and administrative actions private. The public statement should cover only s3:GetObject and the intended object-key pattern, while the ability to modify the policy stays with administrators. This creates a deliberate asymmetry: any anonymous viewer can download approved files, but cannot enumerate the bucket unless you separately grant ListBucket or change or delete anything. Use an isolated bucket for public distribution when there is a risk of accidentally uploading sensitive objects beneath an already public prefix.

After any access change, test with a client that has no AWS credentials to confirm what the world can see. Also test using the intended authenticated application role, because a public anonymous test does not demonstrate that your private backend still works. Review the S3 bucket policy and public-access configuration after the test, not just the visible website response. A successful 200 for the public object alongside a denied anonymous private object is a much stronger acceptance criterion than one successful page load.

Finally, record how to roll back the exception and who is allowed to do it. A configuration that keeps all four blocks enabled is easier to maintain as a company grows and responsibilities change. Where a directly public S3 origin is unavoidable, add regular Access Analyzer review and a deployment check that rejects unexpected public objects. The goal is not merely to turn Access Denied into success today; it is to keep tomorrow's unrelated uploads from silently inheriting a dangerous permission.

Questions people ask after an S3 public access denial

Which of the four S3 Block Public Access settings is causing Access Denied?

Match the denied operation to the setting. BlockPublicPolicy rejects a new public bucket policy; BlockPublicAcls rejects newly public ACL writes; IgnorePublicAcls disregards public ACL permissions; RestrictPublicBuckets restricts reads and some cross-account access when a public policy exists. Check account and bucket settings before changing anything.

Why is my S3 bucket policy with Principal star rejected?

A policy granting anonymous broad access is classified as public, and BlockPublicPolicy rejects its submission when effective at bucket, account, or organization scope. An IAM authorization failure can also prevent a policy update. Verify the exact error and public-access settings before changing them.

Does account-level Block Public Access override bucket settings?

Yes. S3 applies the most restrictive applicable settings across organizational, account, bucket, and access-point contexts. Turning a bucket flag off cannot defeat a corresponding higher-level protection.

Should I turn off all four S3 Block Public Access settings for a website?

Usually no. For a CloudFront OAC architecture you can keep all four enabled and allow CloudFront to retrieve private S3 objects. A direct-public S3 website is a deliberate exception that should be tightly scoped and approved.

Can CloudFront read S3 objects when Block Public Access is enabled?

Yes, with a correctly configured CloudFront Origin Access Control and bucket policy authorizing the CloudFront service principal. Use an S3 bucket origin, not the S3 website endpoint, for this OAC pattern. The bucket remains private to anonymous S3 callers.

Why does an object with a public-read ACL still return 403?

IgnorePublicAcls can prevent S3 from honoring public ACL grants even if those ACLs exist. Object Ownership settings and other permission decisions can also matter. Check the effective configuration instead of relying on an ACL inspection alone.

What changed for S3 buckets in April 2023?

New general purpose S3 buckets began receiving Block Public Access enabled and ACLs disabled by default. That means old examples using public-read ACLs may fail on newer buckets. Bucket policies and CloudFront OAC are generally better contemporary choices.

How do I change Block Public Access with the AWS CLI?

Use aws s3api put-public-access-block with --bucket and --public-access-block-configuration for a bucket. The s3control API handles account-level settings and requires an account ID. Set the complete configuration deliberately and confirm organization rules permit the change.

How can I make only one S3 prefix public?

If a direct-public exception is permitted, use a public GetObject bucket-policy statement scoped to the object ARN ending in the chosen prefix and asterisk. The necessary policy-related public-access controls cannot be effective at a higher level. Verify objects outside the prefix remain private.

Can I use S3 presigned URLs with Block Public Access on?

Yes. Presigned URLs make authenticated requests with the signer’s authorized permissions, rather than granting anonymous public access. Other IAM, bucket, KMS, and organization denies can still prevent access.

What is the difference between BlockPublicAcls and IgnorePublicAcls?

BlockPublicAcls rejects a request attempting to set a public ACL. IgnorePublicAcls does not have to reject the request; it prevents public ACL permissions from becoming effective. Neither automatically deletes historical ACLs.

What is the difference between BlockPublicPolicy and RestrictPublicBuckets?

BlockPublicPolicy prevents submission of a new bucket policy S3 considers public. RestrictPublicBuckets limits access when a public bucket policy exists, including some cross-account permissions. They act at different stages.

How do I list every public S3 bucket in an AWS account?

Use IAM Access Analyzer for S3 and review public-access findings from the S3 External access summary. Create an external access analyzer in each relevant Region and review coverage. Findings may lag configuration changes, so use direct checks for urgent decisions.

Can RestrictPublicBuckets break access for another AWS account?

Yes. When a bucket policy is public, RestrictPublicBuckets can block cross-account access even when another statement names a specific partner. Removing the broad public grant and using a nonpublic targeted policy is often the cleaner fix.

Why am I still getting AccessDenied after disabling Block Public Access?

Disabling the block does not add any allow permission. Check bucket and IAM policies, explicit denies, account ownership, KMS permissions, object key spelling, and higher-level controls. Verify the operation and caller identity.

Is a public S3 bucket ever appropriate?

A deliberate direct-public S3 endpoint can be appropriate for genuinely public static downloads or a static website where that architecture is required and approved. Grant only GetObject on the intended prefix and keep unrelated content isolated. For most CloudFront-hosted sites, a private origin is preferable.

Jake can publish his repair instructions without exposing his customers’ records or weakening every bucket in the account. The next time S3 returns Access Denied, identify the exact operation first, read the effective public-access settings second, and choose the narrowest architecture that serves your visitors. If something on this page does not match the error your own account reports, preserve the request details and compare the relevant controls before changing a security setting.

📌 If you keep one line from this page

Block Public Access decides whether public grants can work; disabling it does not grant anyone permission.

Revision note. Written October 15, 2026, with the April 2023 defaults and CloudFront OAC as the house recommendation. Lock the door, not the whole street: open one prefix, keep the account closed.

Related