Skip to main content
cd ../config-traps
risk/register/account-level-block-public-access-the-silent-reversal.html
AWS Storage Securitycritical severityAWS S3

Account-Level Block Public Access: The Silent Reversal

Severity
critical
Reviewed
15 Jul 2026
Remediation
~20 minutes
Overview

A single Terraform apply that flips all four account-level Block Public Access flags to false on AWS S3 reactivates every dormant wildcard GetObject statement written years earlier, and no bucket-level control remains to stop it because RestrictPublicBuckets no longer applies.

Operational summary

At a glance

Symptom
Account-wide BPA override reactivates every pre-existing wildcard GetObject bucket policy across the account simultaneously.
Likely cause
All four account-level Block Public Access flags set to false to fix one bucket's access error.
Impact
Every bucket with a legacy Principal wildcard statement becomes internet-readable with no deployment event to alert on.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Enforce account-level BPA via SCP denial and require bucket-scoped exemptions with explicit Condition blocks instead of account-wide toggles.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

Account-level S3 Block Public Access (BPA) override masking legacy wildcard bucket policies. The four settings — BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, and RestrictPublicBuckets — are treated as a single on/off toggle rather than four independent controls, and engineers disable all of them at once to solve one narrow problem.

The Default State

New AWS accounts opened since April 2023 ship with account-level BPA fully enabled, which is correct. The trap is introduced later: a CloudFront-to-S3 migration, a static website hosting requirement, or a vendor integration fails with AccessDenied, and the fix committed to the Terraform module is aws_s3_account_public_access_block with all four booleans set to false. This satisfies the one bucket that needed public read access, but the setting is account-wide, not bucket-scoped. Nobody audits the other buckets in the account before merging, because BPA was previously assumed to be a hard backstop against any pre-existing Principal: "*" statement.

The Blast Radius

Every bucket policy in the account is re-evaluated the moment RestrictPublicBuckets flips to false. Old statements granting s3:GetObject to Principal: "*" — written for a 2019 static site, a partner data drop, or a since-abandoned proof of concept — stop being suppressed by the account guardrail and become internet-readable immediately, with no deployment event, no CloudTrail write action, and no application-layer change to trigger existing alerting. S3 Storage Lens and Access Analyzer for S3 will eventually flag the exposure, but by the time those findings surface, objects have already been enumerated and pulled by scanners that continuously probe for exactly this condition. There is no rollback window: the data was public from the second the account setting changed.

The Lead Mechanic Fix

Never disable all four BPA flags together. Run aws s3control put-public-access-block --account-id <id> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true as the enforced baseline, and grant the one exceptional bucket a scoped exemption via its own bucket-level PublicAccessBlockConfiguration, not an account-wide relaxation. Attach an SCP denying s3:PutAccountPublicAccessBlock outside a break-glass role, and require every bucket policy with a wildcard Principal to carry an explicit Condition block — aws:SourceVpce or aws:Referer — validated by a pre-merge Access Analyzer for S3 check before Terraform apply proceeds.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

aws s3control put-public-access-block --account-id <id> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
PublicAccessBlockConfiguration
s3:PutAccountPublicAccessBlock
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources