Infra Audit5 min readUpdated November 4, 2026

Is My S3 Bucket Public? Check It in One Command

Public buckets caused the LA Times, Twilio and PREMINT incidents. Here is the exact check, and the anonymous proof that beats any policy reading.

Run aws s3api get-bucket-policy-status for the intent, then one anonymous curl for the proof. If the curl returns 200, the bucket is public, no matter what the policy says.

aws s3api get-bucket-policy-status --bucket NAME returns IsPublic: true or false. This reads the bucket policy and evaluates whether any statement grants access to Principal *. It is fast and it is what most scanners check.

The policy check: what the config claims

aws s3api get-bucket-policy-status --bucket NAME returns IsPublic: true or false. This reads the bucket policy and evaluates whether any statement grants access to Principal *. It is fast and it is what most scanners check.
aws s3api get-bucket-policy-status --bucket NAME returns IsPublic: true or false. This reads the bucket policy and evaluates whether any statement grants access to Principal *. It is fast and it is what most scanners check. It misses two things: ACL-based grants and the AuthenticatedUsers trick, where a policy grants access to any signed-in AWS account in the world, which is public in practice but not flagged as anonymous.

The anonymous proof: what the world sees

curl -o /dev/null -w '%{http_code}' https://NAME.s3.REGION.amazonaws.com/KEY with no credentials at all. A 200 means an unauthenticated stranger just read your object. This is the evidence that ends the debate, because it is exactly what an attacker does. One request, no tooling, no exploit.
curl -o /dev/null -w '%{http_code}' https://NAME.s3.REGION.amazonaws.com/KEY with no credentials at all. A 200 means an unauthenticated stranger just read your object. This is the evidence that ends the debate, because it is exactly what an attacker does. One request, no tooling, no exploit. We plant a public bucket in our canary AWS account and every audit run detects it with this exact request.

The three ways a bucket becomes public

First: a bucket policy with Principal *. Second: an ACL grant to the AllUsers group, legacy but still found. Third: a policy granting s3:GetObject to the AuthenticatedUsers group, which sounds private and is not. The audit checks all three shapes, because each one has caused a disclosed incident.
First: a bucket policy with Principal *. Second: an ACL grant to the AllUsers group, legacy but still found. Third: a policy granting s3:GetObject to the AuthenticatedUsers group, which sounds private and is not. The audit checks all three shapes, because each one has caused a disclosed incident.

If it stays public

The exposure window opened the day the policy changed, not the day you find it. Scanners enumerate buckets by name pattern around the clock. Every object added after the policy change is one more thing a stranger can copy or overwrite.
The exposure window opened the day the policy changed, not the day you find it. Scanners enumerate buckets by name pattern around the clock. Every object added after the policy change is one more thing a stranger can copy or overwrite. If the bucket holds backups, the restore you planned for the outage is deletable by anyone. Fix is minutes: Block Public Access at account level, then re-run the anonymous curl and expect 403.

4 Tips to Get Started

1

Check every bucket, not just the obvious ones. Names like backups, logs and uploads are the usual suspects.

2

A bucket can be public via policy, via ACL, or via a grant to AuthenticatedUsers. Check all three.

3

Block Public Access at the account level, not per bucket. Per-bucket settings get forgotten.

4

Re-check after every new bucket. Terraform modules and third-party tools create buckets silently.

Ready to Stop Worrying About Infra?

Knowledge is the first step. Get a free 1-hour diagnostic and see where your infrastructure leaks time, money, and focus.

R

Ron Cohen — DevOps engineer & founder, roqy.io

Content reviewed by the roqy.io team. Our guides are based on publicly available data.

Disclaimer: This content is for informational and educational purposes only. It does not constitute professional advice or a guarantee of specific results. Infrastructure needs vary by team, stack, and stage. Consult a qualified engineer for advice tailored to your situation.

Frequently Asked Questions

How do I know if my S3 bucket is public?

Run aws s3api get-bucket-policy-status --bucket NAME. If IsPublic is true, anyone on the internet can read it. The stronger test is anonymous: curl -o /dev/null -w '%{http_code}' https://NAME.s3.REGION.amazonaws.com/KEY returns 200 for a truly public bucket. Policy says intent, the curl proves reality.

What is the risk of a public S3 bucket?

Anyone can list, read or overwrite your objects. In the PREMINT 2022 incident, attackers overwrote a JavaScript file in a public bucket and stole NFT approvals from every visitor. If the bucket holds backups, the backup you think you have can be deleted by a stranger.

Does Block Public Access fix everything?

It blocks public ACLs and policies on that bucket, which covers most cases. It does not cover a bucket shared with another AWS account, an IAM key that can read the bucket, or a snapshot of the data stored elsewhere. Those need separate checks.

Get the DevOps Ecosystem Behind You

One accountable engineer. Full platform behind him. Month-to-month, no lock-in.